home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 24 / Amiga Format AFCD24 (Feb 1998, Issue 108).iso / -in_the_mag- / emulation / amiga / uae-0.7.0b2 / src / compiler.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  136KB  |  4,560 lines

  1.  /*
  2.   * UAE - The Un*x Amiga Emulator
  3.   *
  4.   * m68k emulation
  5.   *
  6.   * Copyright 1996 Bernd Schmidt
  7.   */
  8.  
  9. #include "sysconfig.h"
  10. #include "sysdeps.h"
  11.  
  12. #include "config.h"
  13. #include "options.h"
  14. #include "gensound.h"
  15. #include "sounddep/sound.h"
  16. #include "events.h"
  17. #include "gui.h"
  18. #include "memory.h"
  19. #include "custom.h"
  20. #include "machdep/m68k.h"
  21. #include "readcpu.h"
  22. #include "newcpu.h"
  23. #include "ersatz.h"
  24. #include "blitter.h"
  25. #include "debug.h"
  26. #include "autoconf.h"
  27. #include "compiler.h"
  28.  
  29. #ifdef USE_COMPILER
  30.  
  31. #include <sys/mman.h>
  32.  
  33. char *address_space, *good_address_map;
  34.  
  35. code_execfunc exec_me;
  36. uae_u8 nr_bbs_to_run = 1;
  37. int nr_bbs_start = 40;
  38.  
  39. static int compile_failure;
  40. static int quiet_compile = 1;
  41. int i_want_to_die = 1;
  42. static int n_compiled = 0;
  43. static int n_max_comp = 99999999;
  44. static uaecptr call_only_me = 0;
  45.  
  46. int patched_syscalls = 0;
  47.  
  48. static int count_bits(uae_u16 v)
  49. {
  50.     int bits = 0;
  51.     while (v != 0) {
  52.     if (v & 1)
  53.         bits++;
  54.     v >>= 1;
  55.     }
  56.     return bits;
  57. }
  58.  
  59. static uae_u16 bitswap(uae_u16 v)
  60. {
  61.     uae_u16 newv = 0;
  62.     uae_u16 m1 = 1, m2 = 0x8000;
  63.     int i;
  64.  
  65.     for (i = 0; i < 16; i++) {
  66.     if (v & m1)
  67.         newv |= m2;
  68.     m2 >>= 1;
  69.     m1 <<= 1;
  70.     }
  71.     return newv;
  72. }
  73.  
  74. static long long compiled_hits = 0;
  75.  
  76. /* 16K areas with 512 byte blocks */
  77. #define SUBUNIT_ORDER 9
  78. #define PAGE_SUBUNIT (1 << SUBUNIT_ORDER)
  79. #define PAGE_ALLOC_UNIT (PAGE_SUBUNIT * 32)
  80.  
  81. static int zerofd;
  82. static int zeroff;
  83. static struct code_page *first_code_page;
  84.  
  85. static struct code_page *new_code_page(void)
  86. {
  87.     struct code_page *ncp;
  88.  
  89.     ncp = (struct code_page *)mmap(NULL, PAGE_ALLOC_UNIT,
  90.                    PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE,
  91.                    zerofd, zeroff);
  92.     zeroff += PAGE_ALLOC_UNIT;
  93.     if (ncp) {
  94.     ncp->next = first_code_page;
  95.     first_code_page = ncp;
  96.     ncp->allocmask = 1; /* what a waste */
  97.     }
  98.     return ncp;
  99. }
  100.  
  101. #define NUM_HASH 32768 /* larger values cause some paging on my 16MB machine */
  102. #define HASH_MASK (NUM_HASH-1)
  103. #define MAX_UNUSED_HASH 512
  104.  
  105. static int SCAN_MARK = 1; /* Number of calls after which to scan a function */
  106. static int COMPILE_MARK = 5; /* Number of calls after which to compile a function */
  107.  
  108. /* The main address -> function lookup hashtable. We use the lower bits of
  109.  * the address as hash function. */
  110. static struct hash_entry cpu_hash[NUM_HASH];
  111. /* These aren't really LRU lists... They used to be, but keeping them in that
  112.  * order is costly. The hash LRU list is now a two-part list: Functions that have
  113.  * no code allocated for them are placed at the beginning. Such entries can be
  114.  * recycled when we need a new hash entry. */
  115. static struct hash_block lru_first_block;
  116. static struct hash_entry lru_first_hash;
  117. static struct hash_entry *freelist_hash;
  118. static struct hash_block *freelist_block;
  119. static int num_unused_hash;
  120.  
  121. static int m68k_scan_func(struct hash_entry *);
  122. static int m68k_compile_block(struct hash_block *);
  123.  
  124. static char *alloc_code(struct hash_block *hb, int ninsns)
  125. {
  126.     struct code_page *cp;
  127.     long int allocsize = (ninsns * 32 + PAGE_SUBUNIT-1) & ~(PAGE_SUBUNIT-1);
  128.     uae_u32 allocmask;
  129.     int allocbits;
  130.     int j;
  131.     int last_bit;
  132.  
  133.     if (allocsize >= (PAGE_ALLOC_UNIT - (1 << SUBUNIT_ORDER)))
  134.     return NULL;
  135.     allocbits = (allocsize >> SUBUNIT_ORDER);
  136.     allocmask = (1 << allocbits) - 1;
  137.  
  138.     for (cp = first_code_page; cp != NULL; cp = cp->next) {
  139.     uae_u32 thispage_alloc = cp->allocmask;
  140.     for (j = 1; j < (33 - allocbits); j++) {
  141.         if ((cp->allocmask & (allocmask << j)) == 0) {
  142.         goto found_page;
  143.         }
  144.     }
  145.     }
  146.  
  147.     /* Nothing large enough free: make a new page */
  148.     cp = new_code_page();
  149.     if (cp == NULL)
  150.     return NULL;
  151.     j = 1;
  152.  
  153. found_page:
  154.     /* See whether there is in fact more space for us. If so, allocate all of
  155.      * it. compile_block() will free everything it didn't need. */
  156.  
  157.     allocmask <<= j;
  158.     last_bit = allocbits + j;
  159.     while (last_bit < 32 && (cp->allocmask & (1 << last_bit)) == 0) {
  160.     allocmask |= 1 << last_bit;
  161.     allocsize += PAGE_SUBUNIT;
  162.     last_bit++;
  163.     }
  164.  
  165.     hb->page_allocmask = allocmask;
  166.     hb->cpage = cp;
  167.     cp->allocmask |= allocmask;
  168.     hb->compile_start = ((char *)cp + (j << SUBUNIT_ORDER));
  169.     hb->alloclen = allocsize;
  170.     return hb->compile_start;
  171. }
  172.  
  173. static void remove_hash_from_lists(struct hash_entry *h)
  174. {
  175.     h->lru_next->lru_prev = h->lru_prev;
  176.     h->lru_prev->lru_next = h->lru_next;
  177.  
  178.     h->next->prev = h->prev;
  179.     h->prev->next = h->next;
  180. }
  181.  
  182. static void lru_touch(struct hash_entry *h)
  183. {
  184.     h->lru_next->lru_prev = h->lru_prev;
  185.     h->lru_prev->lru_next = h->lru_next;
  186.  
  187.     h->lru_next = &lru_first_hash;
  188.     h->lru_prev = lru_first_hash.lru_prev;
  189.     h->lru_prev->lru_next = h;
  190.     lru_first_hash.lru_prev = h;
  191. }
  192.  
  193. static void lru_untouch(struct hash_entry *h)
  194. {
  195.     h->lru_next->lru_prev = h->lru_prev;
  196.     h->lru_prev->lru_next = h->lru_next;
  197.  
  198.     h->lru_prev = &lru_first_hash;
  199.     h->lru_next = lru_first_hash.lru_next;
  200.     h->lru_next->lru_prev = h;
  201.     lru_first_hash.lru_next = h;
  202. }
  203.  
  204. static void forget_block(struct hash_block *hb)
  205. {
  206.     struct hash_entry *h = hb->he_first;
  207.  
  208.     hb->lru_next->lru_prev = hb->lru_prev;
  209.     hb->lru_prev->lru_next = hb->lru_next;
  210.  
  211.     hb->lru_next = freelist_block;
  212.     freelist_block = hb;
  213.  
  214.     if (hb->cpage != NULL)
  215.     fprintf(stderr, "Discarding block with code. Tsk.\n");
  216.  
  217.     do {
  218.     struct hash_entry *next = h->next_same_block;
  219.     h->block = NULL;
  220.     h->execute = NULL;
  221.     h->next_same_block = NULL;
  222.     h = next;
  223.     num_unused_hash++;
  224.     lru_untouch(h);
  225.     } while (h != hb->he_first);
  226.     compiler_flush_jsr_stack();
  227. }
  228.  
  229. static void lru_touch_block(struct hash_block *h)
  230. {
  231.     h->lru_next->lru_prev = h->lru_prev;
  232.     h->lru_prev->lru_next = h->lru_next;
  233.  
  234.     h->lru_next = &lru_first_block;
  235.     h->lru_prev = lru_first_block.lru_prev;
  236.     h->lru_prev->lru_next = h;
  237.     lru_first_block.lru_prev = h;
  238. }
  239.  
  240. static __inline__ int check_block(struct hash_block *hb)
  241. {
  242. #ifndef RELY_ON_LOADSEG_DETECTION
  243.     struct hash_entry *h = hb->he_first;
  244.  
  245.     do {
  246.     struct hash_entry *next = h->next_same_block;
  247.     if (h->matchword != *(uae_u32 *)get_real_address(h->addr))
  248.         return 0;
  249.     h = next;
  250.     } while (h != hb->he_first);
  251. #endif
  252.     return 1;
  253. }
  254.  
  255. uae_u32 flush_icache(void)
  256. {
  257.     struct hash_block *hb = lru_first_block.lru_next;
  258.  
  259.     while (hb != &lru_first_block) {
  260.     struct hash_block *next = hb->lru_next;
  261.     if (hb->cpage != NULL) {
  262.         /* Address in chipmem? Then forget about block*/
  263.         if ((hb->he_first->addr & ~0xF80000) != 0xF80000) {
  264.         hb->cpage->allocmask &= ~hb->page_allocmask;
  265.         hb->cpage = NULL;
  266.         forget_block(hb);
  267.         }
  268.     }
  269.     hb = next;
  270.     }
  271.     return m68k_dreg(regs, 0);
  272. }
  273.  
  274. void possible_loadseg(void)
  275. {
  276.     fprintf(stderr, "Possible LoadSeg() detected\n");
  277.     flush_icache();
  278. }
  279.  
  280. static struct hash_block *new_block(void)
  281. {
  282.     struct hash_block *b = freelist_block;
  283.  
  284.     if (b != NULL) {
  285.     freelist_block = b->lru_next;
  286.     } else
  287.     b = (struct hash_block *)malloc(sizeof *b);
  288.     b->nrefs = 0;
  289.     b->cpage = NULL;
  290.     b->he_first = NULL;
  291.     b->translated = b->untranslatable = b->allocfailed = 0;
  292.     return b;
  293. }
  294.  
  295. static struct hash_entry *get_free_hash(void)
  296. {
  297.     struct hash_entry *h;
  298.  
  299.     for (;;) {
  300.     h = freelist_hash;
  301.     if (h != NULL) {
  302.         freelist_hash = h->next_same_block;
  303.         break;
  304.     }
  305.     h = lru_first_hash.lru_next;
  306.     if (num_unused_hash >= MAX_UNUSED_HASH && h->block == NULL
  307.         && !h->locked)
  308.     {
  309.         remove_hash_from_lists(h);
  310.         num_unused_hash--;
  311.         break;
  312.     }
  313.     h = (struct hash_entry *)malloc(sizeof(struct hash_entry));
  314.     h->next_same_block = NULL;
  315.     h->addr = -1;
  316.     break;
  317.     }
  318.     num_unused_hash++;
  319.     h->block = NULL;
  320.     h->ncalls = 0;
  321.     h->locked = h->cacheflush = 0;
  322.     h->execute = NULL;
  323.     return h;
  324. }
  325.  
  326. static struct hash_entry *new_hash(uaecptr addr)
  327. {
  328.     struct hash_entry *h = get_free_hash();
  329.  
  330.     h->addr = addr;
  331.  
  332.     /* Chain the new node */
  333.     h->prev = cpu_hash + ((addr >> 1) & HASH_MASK);
  334.     h->next = h->prev->next;
  335.     h->next->prev = h->prev->next = h;
  336.  
  337.     h->lru_next = &lru_first_hash;
  338.     h->lru_prev = lru_first_hash.lru_prev;
  339.     h->lru_prev->lru_next = h;
  340.     lru_first_hash.lru_prev = h;
  341.  
  342.     h->next_same_block = NULL;
  343.  
  344.     return h;
  345. }
  346. static struct hash_entry *find_hash(uaecptr addr)
  347. {
  348.     struct hash_entry *h;
  349.     struct hash_entry *h1 = cpu_hash + ((addr >> 1) & HASH_MASK);
  350.  
  351.     if (h1->next->addr == addr)
  352.     return h1->next;
  353.  
  354.     for (h = h1->next; h != h1; h = h->next) {
  355.     if (h->addr == addr) {
  356.         /* Put it at the head of the list so that the above shortcut
  357.          * works the next time we come here */
  358.         h->next->prev = h->prev; h->prev->next = h->next;
  359.         h->prev = h1;
  360.         h->next = h1->next;
  361.         h->next->prev = h->prev->next = h;
  362.         return h;
  363.     }
  364.     }
  365.     return NULL;
  366. }
  367.  
  368. static struct hash_entry *get_hash_for_func(uaecptr addr, int mark_locked)
  369. {
  370.     struct hash_entry *h = find_hash(addr);
  371.     if (h == NULL)
  372.     h = new_hash (addr);
  373. #if 0 /* Too expensive */
  374.     else
  375.     lru_touch(h);
  376. #endif
  377.     if (mark_locked)
  378.     h->locked = 1;
  379.     return h;
  380. }
  381.  
  382. static struct hash_entry *get_hash(uaecptr addr)
  383. {
  384.     struct hash_entry *h = get_hash_for_func(addr, 0);
  385.  
  386.     if (h->block == NULL) {
  387.     if (++h->ncalls == SCAN_MARK) {
  388.         m68k_scan_func(h);
  389.     }
  390.     } else
  391.     if (!h->block->untranslatable && h->block->nrefs++ == COMPILE_MARK) {
  392.         lru_touch_block(h->block);
  393.         if (m68k_compile_block(h->block)) {
  394.         h->block->untranslatable = 1;
  395.         } else {
  396.         h->block->translated = 1;
  397.         }
  398.     }
  399.     return h;
  400. }
  401.  
  402. void special_flush_hash(uaecptr addr)
  403. {
  404.     struct hash_entry *h = get_hash_for_func(addr, 0);
  405.  
  406.     h->cacheflush = 1;
  407. }
  408.  
  409. static __inline__ void m68k_setpc_hash(uaecptr newpc)
  410. {
  411.     struct hash_entry *h = get_hash(newpc);
  412.  
  413.     if (h->cacheflush)
  414.     flush_icache();
  415.  
  416.     if (h->execute != NULL) {
  417.     if ((h->addr & 0xF80000) == 0xF80000 || check_block(h->block)) {
  418.         compiled_hits++;
  419.         if (i_want_to_die && (call_only_me == 0 || call_only_me == newpc)) {
  420.         exec_me = h->execute;
  421.         nr_bbs_to_run = nr_bbs_start;
  422.         regs.spcflags |= SPCFLAG_EXEC;
  423.         }
  424.     } else
  425.         flush_icache();
  426.     }
  427.     regs.pc = newpc;
  428.     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
  429. }
  430.  
  431. static __inline__ void m68k_setpc_nohash(uaecptr newpc)
  432. {
  433. #if 0
  434.     /* This is probably not too good for efficiency... FIXME */
  435.     struct hash_entry *h = find_hash(newpc);
  436.  
  437.     if (h != NULL && h->cacheflush)
  438.     flush_icache();
  439. #endif
  440.     regs.pc = newpc;
  441.     regs.pc_p = regs.pc_oldp = get_real_address(newpc);
  442. }
  443.  
  444. void m68k_setpc(uaecptr newpc)
  445. {
  446.     m68k_setpc_hash(newpc);
  447. }
  448.  
  449. void m68k_setpc_fast(uaecptr newpc)
  450. {
  451.     m68k_setpc_nohash(newpc);
  452. }
  453.  
  454. void m68k_setpc_rte(uaecptr newpc)
  455. {
  456.     m68k_setpc_nohash(newpc);
  457. }
  458.  
  459. void m68k_setpc_bcc(uaecptr newpc)
  460. {
  461.     m68k_setpc_hash(newpc);
  462. }
  463.  
  464. static void hash_init(void)
  465. {
  466.     int i;
  467.     struct hash_entry **hepp;
  468.  
  469.     freelist_block = NULL;
  470.     freelist_hash = NULL;
  471.  
  472.     for(i = 0; i < NUM_HASH; i++) {
  473.     cpu_hash[i].next = cpu_hash[i].prev = cpu_hash + i;
  474.     cpu_hash[i].lru_next = cpu_hash[i].lru_prev = NULL;
  475.     cpu_hash[i].block = NULL;
  476.     cpu_hash[i].locked = 0; cpu_hash[i].cacheflush = 0;
  477.     cpu_hash[i].addr = -1;
  478.     }
  479.  
  480.     lru_first_hash.lru_next = lru_first_hash.lru_prev = &lru_first_hash;
  481.     lru_first_block.lru_next = lru_first_block.lru_prev = &lru_first_block;
  482.  
  483.     num_unused_hash = 0;
  484. }
  485.  
  486. static void code_init(void)
  487. {
  488.     first_code_page = NULL;
  489.     zerofd = open("/dev/zero", O_RDWR);
  490.     zeroff = 0;
  491. }
  492.  
  493. #define CC68K_C 16
  494. #define CC68K_V 8
  495. #define CC68K_Z 4
  496. #define CC68K_N 2
  497. #define CC68K_X 1
  498.  
  499. static __inline__ int cc_flagmask_68k(const int cc)
  500. {
  501.     switch(cc){
  502.      case 0: return 0;                       /* T */
  503.      case 1: return 0;                       /* F */
  504.      case 2: return CC68K_C|CC68K_Z;         /* HI */
  505.      case 3: return CC68K_C|CC68K_Z;         /* LS */
  506.      case 4: return CC68K_C;                 /* CC */
  507.      case 5: return CC68K_C;                 /* CS */
  508.      case 6: return CC68K_Z;                 /* NE */
  509.      case 7: return CC68K_Z;                 /* EQ */
  510.      case 8: return CC68K_V;                 /* VC */
  511.      case 9: return CC68K_V;                 /* VS */
  512.      case 10:return CC68K_N;                 /* PL */
  513.      case 11:return CC68K_N;                 /* MI */
  514.      case 12:return CC68K_N|CC68K_V;         /* GE */
  515.      case 13:return CC68K_N|CC68K_V;         /* LT */
  516.      case 14:return CC68K_N|CC68K_V|CC68K_Z; /* GT */
  517.      case 15:return CC68K_N|CC68K_V|CC68K_Z; /* LE */
  518.     }
  519.     abort();
  520.     return 0;
  521. }
  522.  
  523. static __inline__ void translate_step_over_ea(uae_u8 **pcpp, amodes m,
  524.                           wordsizes size)
  525. {
  526.     switch (m) {
  527.      case Areg:
  528.      case Dreg:
  529.      case Aind:
  530.      case Aipi:
  531.      case Apdi:
  532.      case immi:
  533.     break;
  534.  
  535.      case imm:
  536.     if (size == sz_long)
  537.         goto is_long;
  538.     /* fall through */
  539.      case Ad16:
  540.      case PC16:
  541.      case imm0:
  542.      case imm1:
  543.      case absw:
  544.     (*pcpp)+=2;
  545.     break;
  546.      case Ad8r:
  547.      case PC8r:
  548.     {
  549.         uae_u16 extra = *(*pcpp)++;
  550.         extra <<= 8;
  551.         extra |= *(*pcpp)++;
  552.         /* @@@ handle 68020 stuff here */
  553.     }
  554.     break;
  555.      case absl:
  556.      case imm2:
  557.     is_long:
  558.     (*pcpp) += 4;
  559.     break;
  560.     }
  561. }
  562.  
  563. static struct instr *translate_getnextinsn(uae_u8 **pcpp)
  564. {
  565.     uae_u16 opcode;
  566.     struct instr *dp;
  567.  
  568.     opcode = *(*pcpp)++ << 8;
  569.     opcode |= *(*pcpp)++;
  570.  
  571.     if (cpufunctbl[opcode] == op_illg) {
  572.     opcode = 0x4AFC;
  573.     }
  574.     dp = table68k + opcode;
  575.     if (dp->suse) {
  576.     translate_step_over_ea(pcpp, dp->smode, dp->size);
  577.     }
  578.     if (dp->duse) {
  579.     translate_step_over_ea(pcpp, dp->dmode, dp->size);
  580.     }
  581.     return dp;
  582. }
  583.  
  584. #define CB_STACKSIZE 200
  585. #define BB_STACKSIZE 200
  586.  
  587. static uae_u32 condbranch_stack[CB_STACKSIZE];
  588. static int condbranch_src_stack[CB_STACKSIZE];
  589.  
  590. struct bb_info {
  591.     struct hash_entry *h;
  592.     uaecptr stopaddr;
  593.     int can_compile_last;
  594.     struct bb_info *bb_next1, *bb_next2;
  595.     int flags_live_at_end;
  596.     int flags_live_at_start;
  597.     int first_iip, last_iip;
  598. } bb_stack[BB_STACKSIZE];
  599.  
  600. static int top_bb;
  601.  
  602. static uaecptr bcc_target_stack[BB_STACKSIZE];
  603.  
  604. static int new_bcc_target(uaecptr addr)
  605. {
  606.     int i;
  607.  
  608.     for (i = 0; i < top_bb; i++)
  609.     if (bcc_target_stack[i] == addr)
  610.         return 1;
  611.  
  612.     if (top_bb == BB_STACKSIZE)
  613.     return 0;
  614.     bcc_target_stack[top_bb++] = addr;
  615.     return 1;
  616. }
  617.  
  618. static int bcc_compfn(const void *a, const void *b)
  619. {
  620.     uaecptr *a1 = (uaecptr *)a, *b1 = (uaecptr *)b;
  621.  
  622.     if (*a1 == *b1)
  623.     printf("BUG!!\n");
  624.  
  625.     if (*a1 < *b1)
  626.     return 1;
  627.     return -1;
  628. }
  629.  
  630. static int bb_compfn(const void *a, const void *b)
  631. {
  632.     struct bb_info *a1 = (struct bb_info *)a, *b1 = (struct bb_info *)b;
  633.  
  634.     if (a1->h->addr == b1->h->addr)
  635.     printf("BUG!!\n");
  636.  
  637.     if (a1->h->addr < b1->h->addr)
  638.     return -1;
  639.     return 1;
  640. }
  641.  
  642. static int find_basic_blocks(struct hash_entry *h)
  643. {
  644.     int current_bb = 0;
  645.  
  646.     top_bb = 0;
  647.     bcc_target_stack[0] = h->addr;
  648.     new_bcc_target(h->addr);
  649.  
  650.     while (top_bb > current_bb) {
  651.     uaecptr addr = bcc_target_stack[current_bb];
  652.     int ninsns = 0;
  653.     uae_u8 *realpc = get_real_address(addr);
  654.     uae_u8 *rpc_start = realpc;
  655.  
  656.     for(;;) {
  657.         uaecptr thisinsn_addr = (realpc - rpc_start) + addr;
  658.         uae_u8 *rpc_save = realpc;
  659.         struct instr *dp = translate_getnextinsn(&realpc);
  660.         uaecptr nextinsn_addr = (realpc - rpc_start) + addr;
  661.  
  662.         if (dp->mnemo == i_RTS || dp->mnemo == i_RTE
  663.         || dp->mnemo == i_RTR || dp->mnemo == i_RTD
  664.         || dp->mnemo == i_JMP || dp->mnemo == i_ILLG)
  665.         {
  666.         break;
  667.         }
  668.  
  669.         if (dp->mnemo == i_BSR || dp->mnemo == i_JSR) {
  670.         if (!new_bcc_target(nextinsn_addr))
  671.             return 0;
  672.         break;
  673.         }
  674.  
  675.         if (dp->mnemo == i_DBcc) {
  676.         uaecptr newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
  677.         if (!new_bcc_target(nextinsn_addr))
  678.             return 0;
  679.         if (!new_bcc_target(newaddr))
  680.             return 0;
  681.         break;
  682.         }
  683.  
  684.         if (dp->mnemo == i_Bcc) {
  685.         uaecptr newaddr;
  686.         if (dp->smode == imm1)
  687.             newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
  688.         else
  689.             newaddr = thisinsn_addr + 2 + (uae_s8)dp->sreg;
  690.  
  691.         if (dp->cc != 0)
  692.             if (!new_bcc_target(nextinsn_addr))
  693.             return 0;
  694.         if (!new_bcc_target(newaddr))
  695.             return 0;
  696.         break;
  697.         }
  698.     }
  699.     current_bb++;
  700.     }
  701.  
  702.     qsort(bcc_target_stack, top_bb, sizeof (uaecptr), bcc_compfn);
  703.  
  704.     return 1;
  705. }
  706.  
  707. static int m68k_scan_func(struct hash_entry *h)
  708. {
  709.     int i;
  710.     struct hash_block *found_block;
  711.     struct hash_entry **hepp;
  712.  
  713.     if (!find_basic_blocks(h))
  714.     return 0;
  715.  
  716.     found_block = NULL;
  717.  
  718.     /* First, lock the hash entries we already have to prevent grief */
  719.     for (i = 0; i < top_bb; i++) {
  720.     struct hash_entry *h = find_hash(bcc_target_stack[i]);
  721.     if (h != NULL)
  722.         h->locked = 1;
  723.     }
  724.  
  725.     /* Allocate new ones */
  726.     for (i = 0; i < top_bb; i++) {
  727.     struct hash_entry *h = get_hash_for_func(bcc_target_stack[i], 1);
  728.     bb_stack[i].h = h;
  729. #if 0 /* This doesn't work in all cases */
  730.     if (h->block != NULL && h->block != found_block) {
  731.         if (found_block == NULL) {
  732.         if (h->block->cpage != NULL)
  733.             fprintf(stderr, "Found compiled code\n");
  734.         else
  735.             found_block = h->block;
  736.         } else {
  737.         fprintf(stderr, "Multiple blocks found.\n");
  738.         if (h->block->cpage == NULL)
  739.             forget_block(h->block);
  740.         else if (found_block->cpage == NULL) {
  741.             forget_block(found_block);
  742.             found_block = h->block;
  743.         } else
  744.             fprintf(stderr, "Bad case.\n");
  745.         }
  746.     }
  747. #endif
  748.     }
  749.     if (found_block == NULL) {
  750.     found_block = new_block();
  751.  
  752.     found_block->lru_next = &lru_first_block;
  753.     found_block->lru_prev = lru_first_block.lru_prev;
  754.     found_block->lru_prev->lru_next = found_block;
  755.     lru_first_block.lru_prev = found_block;
  756.     }
  757.  
  758.     hepp = &found_block->he_first;
  759.     found_block->he_first = NULL;
  760.     for (i = 0; i < top_bb; i++) {
  761.     struct bb_info *bb = bb_stack + i;
  762.  
  763.     if (bb->h->block == NULL) {
  764.         num_unused_hash--;
  765.         lru_touch(bb->h);
  766.         bb->h->block = found_block;
  767.         *hepp = bb->h;
  768.         hepp = &bb->h->next_same_block;
  769.     }
  770.     }
  771.     *hepp = found_block->he_first;
  772.     return 1;
  773. }
  774.  
  775. struct ea_reg_info {
  776.     enum { eat_reg, eat_imem, eat_amem, eat_const } ea_type;
  777.     int regs_set:16;
  778.     int regs_used:16;
  779.     int nr_scratch;
  780.     uae_u32 temp1, temp2;
  781. };
  782.  
  783. #define MAX_TRANSLATE 2048
  784. struct insn_info_struct {
  785.     uaecptr address;
  786.     struct instr *dp;
  787.     int flags_set;
  788.     int flags_used;
  789.     int flags_live_at_end;
  790.     int jump_target;
  791.     int jumps_to;
  792.     char *compiled_jumpaddr; /* Address to use for jumps to this insn */
  793.     char *compiled_fillin;   /* Address where to put offset if this is a Bcc */
  794.     int regs_set:16;
  795.     int regs_used:16;
  796.     int stop_translation:2;
  797.     int sync_cache:1;
  798.     int sync_flags:1;
  799.     int ccuser_follows:1;
  800. } insn_info [MAX_TRANSLATE];
  801.  
  802. #define EA_NONE 0
  803. #define EA_LOAD 1
  804. #define EA_STORE 2
  805. #define EA_MODIFY 4
  806.  
  807. #if 0
  808. static void analyze_ea_for_insn(amodes mode, int reg, wordsizes size,
  809.                 struct ea_reg_info *eai,
  810.                 uae_u8 **pcpp, uaecptr pca,
  811.                 int ea_purpose)
  812. {
  813.     uae_u8 *p = *pcpp;
  814.  
  815.     switch(mode) {
  816.      case Dreg:
  817.     eai->ea_type = eat_reg;
  818.     if (size != sz_long && (ea_purpose & EA_STORE))
  819.         ea_purpose |= EA_LOAD;
  820.     if (ea_purpose & EA_LOAD)
  821.         eai->regs_used |= 1 << reg;
  822.     if (ea_purpose & EA_STORE)
  823.         eai->regs_set |= 1 << reg;
  824.     break;
  825.  
  826.      case Areg:
  827.     eai->ea_type = eat_reg;
  828.     if (size != sz_long && (ea_purpose & EA_STORE))
  829.         printf("Areg != long\n");
  830.     if (ea_purpose & EA_LOAD)
  831.         eai->regs_used |= 1 << (8+reg);
  832.     if (ea_purpose & EA_STORE)
  833.         eai->regs_set |= 1 << (8+reg);
  834.     break;
  835.  
  836.      case Ad16:
  837.      case Aind:
  838.      case Apdi:
  839.      case Aipi:
  840.     eai->ea_type = eat_imem;
  841.     eai->regs_used |= 1 << (8+reg);
  842.     break;
  843.  
  844.      case Ad8r:
  845.     eai->ea_type = eat_imem;
  846.     pii->regs_used |= 1 << (8+reg);
  847.  
  848.     eai->temp = (uae_u16)((*p << 8) | *(p+1));
  849.     r = (eai->temp & 0x7000) >> 12;
  850.     (*pcpp) += 2; p += 2;
  851.  
  852.     if (eai->temp1 & 0x8000)
  853.         pii->regs_used |= 1 << (8+r);
  854.     else
  855.         pii->regs_used |= 1 << r;
  856.     break;
  857.  
  858.      case PC8r:
  859.     eai->ea_type = eat_imem;
  860.     eai->temp1 = (uae_u16)do_get_mem_word((uae_u16 *)p);
  861.     eai->temp2 = pca + (uae_s8)eai->temp1;
  862.     (*pcpp) += 2; p += 2;
  863.     r = (eai->temp1 & 0x7000) >> 12;
  864.  
  865.     if (eai->temp1 & 0x8000)
  866.         pii->regs_used |= 1 << (8+r);
  867.     else
  868.         pii->regs_used |= 1 << r;
  869.     break;
  870.  
  871.      case PC16:
  872.     eai->ea_type = eat_amem;
  873.     eai->temp1 = pca + (uae_s16)do_get_mem_word((uae_u16 *)p);
  874.     (*pcpp) += 2;
  875.     break;
  876.  
  877.      case absw:
  878.     eai->ea_type = eat_amem;
  879.     eai->temp1 = (uae_s16)do_get_mem_word((uae_u16 *)p);
  880.     (*pcpp) += 2;
  881.     break;
  882.  
  883.      case absl:
  884.     eai->ea_type = eat_amem;
  885.     eai->temp1 = (uae_s32)do_get_mem_long((uae_u32 *)p);
  886.     (*pcpp) += 4;
  887.     break;
  888.  
  889.      case imm:
  890.     if (size == sz_long)
  891.         goto imm2_const;
  892.     if (size == sz_word)
  893.         goto imm1_const;
  894.  
  895.     /* fall through */
  896.      case imm0:
  897.     eai->ea_type = eat_imm;
  898.     eai->temp1 = (uae_s8)*(p+1);
  899.     (*pcpp) += 2;
  900.     break;
  901.  
  902.      case imm1:
  903.     imm1_const:
  904.     eai->ea_type = eat_imm;
  905.     eai->temp1 = (uae_s16)do_get_mem_word((uae_u16 *)p);
  906.     (*pcpp) += 2;
  907.     break;
  908.  
  909.      case imm2:
  910.     imm2_const:
  911.     eai->ea_type = eat_imm;
  912.     eai->temp1 = (uae_s32)do_get_mem_long((uae_u32 *)p);
  913.     (*pcpp) += 4;
  914.     break;
  915.  
  916.      case immi:
  917.     eai->ea_type = eat_imm;
  918.     eai->temp1 = (uae_s8)reg;
  919.     break;
  920.  
  921.      default:
  922.     break;
  923.     }
  924. }
  925. #endif
  926. static struct bb_info *find_bb(struct hash_entry *h)
  927. {
  928.     int i;
  929.  
  930.     if (h == NULL)
  931.     printf("Bug...\n");
  932.  
  933.     for (i = 0; i < top_bb; i++)
  934.     if (bb_stack[i].h == h)
  935.         return bb_stack + i;
  936.     if (!quiet_compile)
  937.     fprintf(stderr, "BB not found!\n");
  938.     return NULL;
  939. }
  940.  
  941. static int m68k_scan_block(struct hash_block *hb, int *movem_count)
  942. {
  943.     struct hash_entry *h = hb->he_first;
  944.     int i, iip, last_iip;
  945.     int changed, round;
  946.  
  947.     top_bb = 0;
  948.  
  949.     do {
  950.     struct bb_info *bb = bb_stack + top_bb;
  951.     bb->h = h;
  952.     bb->bb_next1 = NULL;
  953.     bb->bb_next2 = NULL;
  954.     h = h->next_same_block;
  955.     top_bb++;
  956.     } while (h != hb->he_first);
  957.  
  958.     qsort(bb_stack, top_bb, sizeof (struct bb_info), bb_compfn);
  959.  
  960.     *movem_count = 0;
  961.  
  962.     iip = 0;
  963.     for (i = 0; i < top_bb; i++) {
  964.     struct bb_info *bb = bb_stack + i;
  965.     uae_u8 *realpc = get_real_address(bb->h->addr);
  966.     uae_u8 *rpc_start = realpc;
  967.     uaecptr stop_addr = 0;
  968.     int live_at_start = 31, may_clear_las = 31;
  969.     struct insn_info_struct *prev_ii = NULL;
  970.  
  971.     if (i < top_bb - 1)
  972.         stop_addr = (bb+1)->h->addr;
  973.     bb->first_iip = iip;
  974.  
  975.     for (;;) {
  976.         struct insn_info_struct *thisii = insn_info + iip;
  977.         uaecptr thisinsn_addr = (realpc - rpc_start) + bb->h->addr;
  978.         uae_u8 *rpc_save = realpc;
  979.         struct instr *dp = translate_getnextinsn(&realpc);
  980.         uaecptr nextinsn_addr = (realpc - rpc_start) + bb->h->addr;
  981.  
  982.         int fset = dp->flagdead == -1 ? 31 : dp->flagdead;
  983.         int fuse = dp->flaglive == -1 ? 31 : dp->flaglive;
  984.  
  985.         if (thisinsn_addr == stop_addr) {
  986.         bb->bb_next1 = find_bb (find_hash (thisinsn_addr));
  987.         break;
  988.         }
  989.  
  990.         if (dp->mnemo == i_Scc || dp->mnemo == i_Bcc || dp->mnemo == i_DBcc) {
  991.         fset = 0, fuse = cc_flagmask_68k(dp->cc);
  992.         if (prev_ii && dp->mnemo != i_Scc) /* Don't use Scc here: ea can cause an exit */
  993.             prev_ii->ccuser_follows = 1;
  994.         }
  995.  
  996.         may_clear_las &= ~fuse;
  997.         live_at_start &= ~(fset & may_clear_las);
  998.  
  999.         thisii->dp = dp;
  1000.         thisii->address = thisinsn_addr;
  1001.         thisii->stop_translation = 0;
  1002.         thisii->ccuser_follows = 0;
  1003. /*        thisii->have_reginfo = 0;*/
  1004.         thisii->jump_target = 0;
  1005.         thisii->sync_cache = thisii->sync_flags = 0;
  1006.         thisii->flags_set = fset;
  1007.         thisii->flags_used = fuse;
  1008.         thisii->regs_set = 0;
  1009.         thisii->regs_used = 0;
  1010.         iip++;
  1011.         if (iip == MAX_TRANSLATE)
  1012.         return 0;
  1013.  
  1014.         if (dp->mnemo == i_RTS || dp->mnemo == i_RTE
  1015.         || dp->mnemo == i_RTR || dp->mnemo == i_RTD
  1016.         || dp->mnemo == i_JMP || dp->mnemo == i_ILLG)
  1017.         {
  1018.         thisii->flags_used = 31;
  1019.         thisii->regs_used = 65535;
  1020.         thisii->stop_translation = dp->mnemo == i_RTS || dp->mnemo == i_JMP ? 2 : 1;
  1021.         break;
  1022.         }
  1023.         if (dp->mnemo == i_BSR || dp->mnemo == i_JSR)
  1024.         {
  1025.         thisii->flags_used = 31;
  1026.         thisii->regs_used = 65535;
  1027.         bb->can_compile_last = 1;
  1028.         bb->bb_next1 = find_bb (get_hash_for_func (nextinsn_addr, 1));
  1029.         if (bb->bb_next1 == NULL)
  1030.             thisii->stop_translation = 1;
  1031.         break;
  1032.         }
  1033.  
  1034.         if (dp->mnemo == i_DBcc) {
  1035.         uaecptr newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
  1036.         bb->can_compile_last = 1;
  1037.         bb->bb_next1 = find_bb (get_hash_for_func (newaddr, 1));
  1038.         if (bb->bb_next1 == NULL)
  1039.             thisii->stop_translation = 1;
  1040.         bb->bb_next2 = find_bb (get_hash_for_func (nextinsn_addr, 1));
  1041.         if (bb->bb_next2 == NULL)
  1042.             thisii->stop_translation = 1;
  1043.         thisii->regs_used = 65535;
  1044.         break;
  1045.         }
  1046.  
  1047.         if (dp->mnemo == i_Bcc) {
  1048.         uaecptr newaddr;
  1049.         if (dp->smode == imm1)
  1050.             newaddr = thisinsn_addr + 2 + (uae_s16)((*(rpc_save+2) << 8) | *(rpc_save+3));
  1051.         else
  1052.             newaddr = thisinsn_addr + 2 + (uae_s8)dp->sreg;
  1053.         bb->can_compile_last = 1;
  1054.         bb->bb_next1 = find_bb(get_hash_for_func(newaddr, 1));
  1055.         if (bb->bb_next1 == NULL)
  1056.             thisii->stop_translation = 1;
  1057.         if (dp->cc != 0) {
  1058.             bb->bb_next2 = find_bb(get_hash_for_func(nextinsn_addr, 1));
  1059.             if (bb->bb_next2 == NULL)
  1060.             thisii->stop_translation = 1;
  1061.         }
  1062.         thisii->regs_used = 65535;
  1063.         break;
  1064.         }
  1065.  
  1066.         if (dp->mnemo == i_MVMLE || dp->mnemo == i_MVMEL) {
  1067.         uae_u16 regmask = (*(rpc_save + 2) << 8) | (*(rpc_save + 3));
  1068.         *movem_count += count_bits(regmask);
  1069.         if (dp->dmode == Apdi)
  1070.             regmask = bitswap(regmask);
  1071.         if (dp->mnemo == i_MVMLE)
  1072.             thisii->regs_used = regmask;
  1073.         else
  1074.             thisii->regs_set = regmask;
  1075.         }
  1076.  
  1077.         prev_ii = thisii;
  1078.     }
  1079.     bb->last_iip = iip - 1;
  1080.     bb->flags_live_at_start = live_at_start;
  1081.     }
  1082.     last_iip = iip;
  1083.     round = 0;
  1084.     do {
  1085.     changed = 0;
  1086.     for (i = 0; i < top_bb; i++) {
  1087.         struct bb_info *bb = bb_stack + i;
  1088.         int mnemo;
  1089.         int current_live;
  1090.         struct instr *dp;
  1091.  
  1092.         iip = bb->last_iip;
  1093.         mnemo = insn_info[iip].dp->mnemo;
  1094.  
  1095.         /* Fix up branches */
  1096.         if (round == 0 && (mnemo == i_DBcc || mnemo == i_Bcc)) {
  1097.         if (bb->bb_next1 != NULL) {
  1098.             insn_info[bb->last_iip].jumps_to = bb->bb_next1->first_iip;
  1099.             insn_info[bb->bb_next1->first_iip].jump_target = 1;
  1100.         }
  1101.         }
  1102.  
  1103.         /* And take care of flag life information */
  1104.         dp = insn_info[iip].dp;
  1105.         if (insn_info[iip].stop_translation)
  1106.         current_live = 31;
  1107.         else if (dp->mnemo == i_DBcc || dp->mnemo == i_Bcc) {
  1108.         current_live = 0;
  1109.         if (bb->bb_next1 != NULL)
  1110.             current_live |= bb->bb_next1->flags_live_at_start;
  1111.         if (bb->bb_next2 != NULL)
  1112.             current_live |= bb->bb_next2->flags_live_at_start;
  1113.         } else {
  1114.         if (bb->bb_next1 == NULL && bb->bb_next2 == NULL)
  1115.             fprintf(stderr, "Can't happen\n");
  1116.         current_live = 0;
  1117.         if (bb->bb_next1 != NULL)
  1118.             current_live |= bb->bb_next1->flags_live_at_start;
  1119.         if (bb->bb_next2 != NULL)
  1120.             current_live |= bb->bb_next2->flags_live_at_start;
  1121.         }
  1122.  
  1123.         do {
  1124.         insn_info[iip].flags_live_at_end = current_live;
  1125.         current_live &= ~insn_info[iip].flags_set;
  1126.         current_live |= insn_info[iip].flags_used;
  1127.         } while (iip-- != bb->first_iip);
  1128.  
  1129.         if (bb->flags_live_at_start != current_live && !quiet_compile)
  1130.         fprintf(stderr, "Fascinating %d!\n", round), changed = 1;
  1131.         bb->flags_live_at_start = current_live;
  1132.     }
  1133.     round++;
  1134.     } while (changed);
  1135.     return last_iip;
  1136. }
  1137.  
  1138. #define MAX_JSRS 4096 /* must be a power of two */
  1139.  
  1140. static uaecptr jsr_rets[MAX_JSRS];
  1141. static struct hash_entry *jsr_hash[MAX_JSRS];
  1142. static int jsr_num;
  1143. static struct hash_entry dummy_hash; /* This is for safety purposes only */
  1144.  
  1145.  
  1146. static void jsr_stack_init(void)
  1147. {
  1148.     jsr_num = 0;
  1149.     dummy_hash.execute = NULL;
  1150. }
  1151.  
  1152. void compiler_flush_jsr_stack(void)
  1153. {
  1154.     jsr_num = 0;
  1155. }
  1156.  
  1157. void m68k_do_rts(void)
  1158. {
  1159.     m68k_setpc(get_long(m68k_areg(regs, 7)));
  1160.     m68k_areg(regs, 7) += 4;
  1161.     if (jsr_num > 0)
  1162.     jsr_num--;
  1163. }
  1164.  
  1165. __inline__ void m68k_do_jsr(uaecptr oldpc, uaecptr dest)
  1166. {
  1167.     struct hash_entry *h = find_hash(oldpc);
  1168.  
  1169.     if (jsr_num == MAX_JSRS)
  1170.     compiler_flush_jsr_stack();
  1171.     if (h == NULL) {
  1172.     jsr_hash[jsr_num] = &dummy_hash;
  1173.     jsr_rets[jsr_num++] = 0xC0DEDBAD;
  1174.     } else {
  1175.     jsr_hash[jsr_num] = h;
  1176.     jsr_rets[jsr_num++] = oldpc;
  1177.     }
  1178.     m68k_areg(regs, 7) -= 4;
  1179.     put_long(m68k_areg(regs, 7), oldpc);
  1180.     m68k_setpc(dest);
  1181. }
  1182.  
  1183. void m68k_do_bsr(uaecptr oldpc, uae_s32 offset)
  1184. {
  1185.     m68k_do_jsr(oldpc, m68k_getpc() + offset);
  1186. }
  1187.  
  1188. /* Here starts the actual compiling part */
  1189.  
  1190. static char *compile_current_addr;
  1191. static char *compile_last_addr;
  1192.  
  1193. static __inline__ void assemble(uae_u8 a)
  1194. {
  1195.     if (compile_current_addr < compile_last_addr) {
  1196.     *compile_current_addr++ = a;
  1197.     } else {
  1198.     compile_failure = 1;
  1199.     }
  1200. }
  1201.  
  1202. static __inline__ void assemble_ulong(uae_u32 a)
  1203. {
  1204.     assemble(a);
  1205.     assemble(a >> 8);
  1206.     assemble(a >> 16);
  1207.     assemble(a >> 24);
  1208. }
  1209.  
  1210. static __inline__ void assemble_ulong_68k(uae_u32 a)
  1211. {
  1212.     assemble(a >> 24);
  1213.     assemble(a >> 16);
  1214.     assemble(a >> 8);
  1215.     assemble(a);
  1216. }
  1217.  
  1218. static __inline__ void assemble_uword(uae_u16 a)
  1219. {
  1220.     assemble(a);
  1221.     assemble(a >> 8);
  1222. }
  1223.  
  1224. static __inline__ void assemble_long(void *a)
  1225. {
  1226.     assemble_ulong((uae_u32)a);
  1227. }
  1228.  
  1229. static __inline__ void compile_org(char *addr)
  1230. {
  1231.     compile_current_addr = addr;
  1232. }
  1233.  
  1234. static __inline__ char *compile_here(void)
  1235. {
  1236.     return compile_current_addr;
  1237. }
  1238.  
  1239. #define r_EAX 0
  1240. #define r_ECX 1
  1241. #define r_EDX 2
  1242. #define r_EBX 3
  1243. #define r_ESP 4
  1244. #define r_EBP 5
  1245. #define r_ESI 6
  1246. #define r_EDI 7
  1247.  
  1248. #define r_AH 0x84
  1249. #define r_CH 0x85
  1250. #define r_DH 0x86
  1251. #define r_BH 0x87
  1252.  
  1253. #define ALL_X86_REGS 255
  1254. #define ADDRESS_X86_REGS ((1 << r_EBP) | (1 << r_ESI) | (1 << r_EDI))
  1255. #define DATA_X86_REGS ((1 << r_EAX) | (1 << r_EDX) | (1 << r_EBX) | (1 << r_ECX))
  1256.  
  1257. #define BO_NORMAL 0
  1258. #define BO_SWAPPED_LONG 1
  1259. #define BO_SWAPPED_WORD 2
  1260.  
  1261. struct register_mapping {
  1262.     int dreg_map[8], areg_map[8]; /* 68000 register cache */
  1263.     int x86_const_offset[8];
  1264.     int x86_dirty[8];
  1265.     int x86_cache_reg[8]; /* Regs used for the 68000 register cache */
  1266.     int x86_cr_type[8]; /* Caching data or address register? */
  1267.     int x86_locked[8]; /* Regs used for some purpose */
  1268.     int x86_users[8];
  1269.     int x86_byteorder[8];
  1270.     int x86_verified[8];
  1271. };
  1272.  
  1273. /*
  1274.  * First, code to compile some primitive x86 instructions
  1275.  */
  1276.  
  1277. static void compile_lea_reg_with_offset(int dstreg, int srcreg, uae_u32 srcoffs)
  1278. {
  1279.     assemble(0x8D);
  1280.     if (srcreg == -2) {
  1281.     assemble(0x05 + 8*dstreg);
  1282.     assemble_ulong(srcoffs);
  1283.     } else if ((uae_s32)srcoffs >= -128 && (uae_s32)srcoffs <= 127) {
  1284.     assemble(0x40 + 8*dstreg + srcreg);
  1285.     assemble(srcoffs);
  1286.     } else {
  1287.     assemble(0x80 + 8*dstreg + srcreg);
  1288.     assemble_ulong(srcoffs);
  1289.     }
  1290. }
  1291.  
  1292. static void compile_move_reg_reg(int dstreg, int srcreg, wordsizes size)
  1293. {
  1294.     if (size == sz_byte
  1295.     && (((1 << dstreg) & DATA_X86_REGS) == 0
  1296.         || ((1 << srcreg) & DATA_X86_REGS) == 0))
  1297.     {
  1298.     fprintf(stderr, "Moving wrong register types!\n");
  1299.     }
  1300.     if (size == sz_word)
  1301.     assemble(0x66);
  1302.     if (size == sz_byte)
  1303.     assemble(0x88);
  1304.     else
  1305.     assemble(0x89);
  1306.     assemble(0xC0 + dstreg + 8*srcreg);
  1307. }
  1308.  
  1309. static void compile_move_between_reg_mem_regoffs(int dstreg, int srcreg,
  1310.                          uae_u32 srcoffs, wordsizes size,
  1311.                          int code)
  1312. {
  1313.     if (size == sz_byte && (dstreg & 0x80) != 0)
  1314.     dstreg &= ~0x80;
  1315.     else if ((size == sz_byte
  1316.           && ((1 << dstreg) & DATA_X86_REGS) == 0)
  1317.          || (size != sz_byte && (dstreg & 0x80) != 0))
  1318.     {
  1319.     fprintf(stderr, "Moving wrong register types!\n");
  1320.     }
  1321.     if (size == sz_word)
  1322.     assemble(0x66);
  1323.     if (size == sz_byte)
  1324.     assemble(code);
  1325.     else
  1326.     assemble(code + 1);
  1327.  
  1328.     if (srcreg == -2) {
  1329.     assemble(0x05 + 8*dstreg);
  1330.     assemble_ulong(srcoffs);
  1331.     } else if ((uae_s32)srcoffs >= -128 && (uae_s32)srcoffs <= 127) {
  1332.     assemble(0x40 + 8*dstreg + srcreg);
  1333.     assemble(srcoffs);
  1334.     } else {
  1335.     assemble(0x80 + 8*dstreg + srcreg);
  1336.     assemble_ulong(srcoffs);
  1337.     }
  1338. }
  1339.  
  1340. static void compile_move_reg_from_mem_regoffs(int dstreg, int srcreg,
  1341.                           uae_u32 srcoffs, wordsizes size)
  1342. {
  1343.     compile_move_between_reg_mem_regoffs(dstreg, srcreg, srcoffs, size, 0x8A);
  1344. }
  1345.  
  1346. static void compile_move_reg_to_mem_regoffs(int dstreg, uae_u32 dstoffs,
  1347.                         int srcreg, wordsizes size)
  1348. {
  1349.     compile_move_between_reg_mem_regoffs(srcreg, dstreg, dstoffs, size, 0x88);
  1350. }
  1351.  
  1352. static void compile_byteswap(int x86r, wordsizes size, int save_flags)
  1353. {
  1354.     switch(size) {
  1355.      case sz_word:
  1356.     if (save_flags)
  1357.         assemble(0x9C);
  1358.     assemble(0x66); /* rolw $8,x86r */
  1359.     assemble(0xC1);
  1360.     assemble(0xC0 + x86r);
  1361.     assemble(8);
  1362.     if (save_flags)
  1363.         assemble(0x9D);
  1364.     break;
  1365.      case sz_long:
  1366.     assemble(0x0F); /* bswapl x86r */
  1367.     assemble(0xC8+x86r);
  1368.     break;
  1369.      default:
  1370.     break;
  1371.     }
  1372. }
  1373.  
  1374. static void compile_force_byteorder(struct register_mapping *map, int x86r,
  1375.                     int desired_bo, int save_flags)
  1376. {
  1377.     if (x86r < 0 || map->x86_byteorder[x86r] == desired_bo)
  1378.     return;
  1379.  
  1380.     if (map->x86_byteorder[x86r] == BO_SWAPPED_LONG)
  1381.     compile_byteswap(x86r, sz_long, save_flags);
  1382.     else if (map->x86_byteorder[x86r] == BO_SWAPPED_WORD)
  1383.     compile_byteswap(x86r, sz_word, save_flags);
  1384.  
  1385.     if (desired_bo == BO_SWAPPED_LONG)
  1386.     compile_byteswap(x86r, sz_long, save_flags);
  1387.     else if (desired_bo == BO_SWAPPED_WORD)
  1388.     compile_byteswap(x86r, sz_word, save_flags);
  1389.     map->x86_byteorder[x86r] = desired_bo;
  1390. }
  1391.  
  1392. /* Add a constant offset to a x86 register. If it's in the cache, make sure
  1393.  * we update the const_offset value. The flags are unaffected by this */
  1394.  
  1395. static void compile_offset_reg(struct register_mapping *map, int x86r,
  1396.                    uae_u32 offset)
  1397. {
  1398.     int cached_68k;
  1399.  
  1400.     if (offset == 0 || x86r == -1 || x86r == -2)
  1401.     return;
  1402.  
  1403.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1404.     cached_68k = map->x86_cache_reg[x86r];
  1405.     if (cached_68k != -1) {
  1406.     map->x86_const_offset[x86r] -= offset;
  1407.     map->x86_dirty[x86r] = 1;
  1408.     }
  1409.     compile_lea_reg_with_offset(x86r, x86r, offset);
  1410. }
  1411.  
  1412. static int get_unused_x86_register(struct register_mapping *map)
  1413. {
  1414.     int x86r;
  1415.     for (x86r = 0; x86r < 24; x86r++) {
  1416.     if (map->x86_cache_reg[x86r] != -1)
  1417.         continue;
  1418.     if (map->x86_users[x86r] > 0)
  1419.         continue;
  1420.  
  1421.     map->x86_verified[x86r] = 0;
  1422.     map->x86_byteorder[x86r] = BO_NORMAL;
  1423.     return x86r;
  1424.     }
  1425.     return -1;
  1426. }
  1427.  
  1428. /*
  1429.  * sync_reg() may not touch the flags
  1430.  * If may_clobber is 1 and the reg had an offset, the reg will be offsetted
  1431.  * by this function
  1432.  */
  1433. static void sync_reg(struct register_mapping *map, int x86r, void *m68kr,
  1434.              uae_u32 offset, int dirty, int may_clobber)
  1435. {
  1436.     if (dirty || offset != 0)
  1437.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1438.     if (offset != 0) {
  1439.     if (may_clobber) {
  1440.         compile_lea_reg_with_offset(x86r, x86r, offset);
  1441.         dirty = 1;
  1442.     } else {
  1443.         int tmpr = get_unused_x86_register(map);
  1444.         if (tmpr != -1) {
  1445.         compile_lea_reg_with_offset(tmpr, x86r, offset);
  1446.         x86r = tmpr;
  1447.         dirty = 1;
  1448.         } else {
  1449.         compile_lea_reg_with_offset(x86r, x86r, offset);
  1450.         assemble(0x89);          /* movl x86r,m68kr */
  1451.         assemble(0x05 + (x86r << 3));
  1452.         assemble_long(m68kr);
  1453.         compile_lea_reg_with_offset(x86r, x86r, -offset);
  1454.         return;
  1455.         }
  1456.     }
  1457.     }
  1458.     if (dirty) {
  1459.     assemble(0x89);          /* movl x86r,m68kr */
  1460.     assemble(0x05 + (x86r << 3));
  1461.     assemble_long(m68kr);
  1462.     }
  1463. }
  1464.  
  1465. static void sync_reg_cache(struct register_mapping *map, int flush)
  1466. {
  1467.     int i;
  1468.  
  1469.     for (i = 0; i < 8; i++) {
  1470.     int cr68k = map->x86_cache_reg[i];
  1471.     if (cr68k != -1) {
  1472.         if (map->x86_cr_type[i] == 1) {
  1473.         sync_reg(map, i, regs.regs + cr68k, map->x86_const_offset[i], map->x86_dirty[i], 1);
  1474.         if (flush)
  1475.             map->dreg_map[cr68k] = -1;
  1476.         } else {
  1477.         sync_reg(map, i, regs.regs + 8 + cr68k, map->x86_const_offset[i], map->x86_dirty[i], 1);
  1478.         if (flush)
  1479.             map->areg_map[cr68k] = -1;
  1480.         }
  1481.         if (flush)
  1482.         map->x86_cache_reg[i] = -1;
  1483.         map->x86_const_offset[i] = 0;
  1484.     }
  1485.     }
  1486.     memset(map->x86_dirty, 0, sizeof map->x86_dirty);
  1487. }
  1488.  
  1489. static void remove_x86r_from_cache(struct register_mapping *map, int x86r,
  1490.                    int may_clobber)
  1491. {
  1492.     int j;
  1493.     int reg_68k;
  1494.  
  1495.     if (x86r == -1)
  1496.     return;
  1497.  
  1498.     reg_68k = map->x86_cache_reg[x86r];
  1499.  
  1500.     if (reg_68k == -1)
  1501.     return;
  1502.  
  1503.     if (map->x86_cr_type[x86r] == 1) {
  1504.     map->dreg_map[reg_68k] = -1;
  1505.     sync_reg(map, x86r, regs.regs + reg_68k, map->x86_const_offset[x86r],
  1506.          map->x86_dirty[x86r], may_clobber);
  1507.     } else {
  1508.     map->areg_map[reg_68k] = -1;
  1509.     sync_reg(map, x86r, regs.regs + 8 + reg_68k,  map->x86_const_offset[x86r],
  1510.          map->x86_dirty[x86r], may_clobber);
  1511.     }
  1512.     map->x86_dirty[x86r] = 0;
  1513.     map->x86_cache_reg[x86r] = -1;
  1514.     map->x86_const_offset[x86r] = 0;
  1515.     map->x86_verified[x86r] = 0;
  1516.     map->x86_byteorder[x86r] = BO_NORMAL;
  1517. }
  1518.  
  1519. static int get_free_x86_register(struct register_mapping *map,
  1520.                  int preferred_mask)
  1521. {
  1522.     int cnt;
  1523.     for (cnt = 0; cnt < 24; cnt++) {
  1524.     int x86r = cnt & 7;
  1525.     /* In the first two passes, try to get one of the preferred regs */
  1526.     if (cnt < 16 && ((1 << x86r) & preferred_mask) == 0)
  1527.         continue;
  1528.     /* In the first pass, don't discard any registers from the cache */
  1529.     if (cnt < 8 && map->x86_cache_reg[x86r] != -1)
  1530.         continue;
  1531.     /* Never use locked registers */
  1532.     if (map->x86_users[x86r] > 0)
  1533.         continue;
  1534.  
  1535.     remove_x86r_from_cache(map, x86r, 1);
  1536.     map->x86_dirty[x86r] = 0;
  1537.     map->x86_cache_reg[x86r] = -1;
  1538.     map->x86_const_offset[x86r] = 0;
  1539.     map->x86_verified[x86r] = 0;
  1540.     map->x86_byteorder[x86r] = BO_NORMAL;
  1541.     return x86r;
  1542.     }
  1543.     printf("Out of registers!\n");
  1544.     return -1;
  1545. }
  1546.  
  1547. static int get_typed_x86_register(struct register_mapping *map,
  1548.                   int preferred_mask)
  1549. {
  1550.     int cnt;
  1551.     for (cnt = 0; cnt < 16; cnt++) {
  1552.     int x86r = cnt & 7;
  1553.     /* Get one of the preferred regs */
  1554.     if (((1 << x86r) & preferred_mask) == 0)
  1555.         continue;
  1556.     /* In the first pass, don't discard any registers from the cache */
  1557.     if (cnt < 8 && map->x86_cache_reg[x86r] != -1)
  1558.         continue;
  1559.     /* Never use locked registers */
  1560.     if (map->x86_users[x86r] > 0)
  1561.         continue;
  1562.  
  1563.     remove_x86r_from_cache(map, x86r, 1);
  1564.     map->x86_dirty[x86r] = 0;
  1565.     map->x86_cache_reg[x86r] = -1;
  1566.     map->x86_const_offset[x86r] = 0;
  1567.     map->x86_verified[x86r] = 0;
  1568.     map->x86_byteorder[x86r] = BO_NORMAL;
  1569.     return x86r;
  1570.     }
  1571.     printf("Out of type registers!\n");
  1572.     return -1;
  1573. }
  1574.  
  1575. static void compile_unlock_reg(struct register_mapping *map, int reg)
  1576. {
  1577.     if (reg >= 0) {
  1578.     if (--map->x86_users[reg] == 0)
  1579.         map->x86_locked[reg] = 0;
  1580.  
  1581.     }
  1582. }
  1583.  
  1584. static void lock_reg(struct register_mapping *map, int x86r, int lock_type)
  1585. {
  1586. #if 1
  1587.     switch (map->x86_locked[x86r]) {
  1588.      case 0:
  1589.     if (map->x86_users[x86r] != 0)
  1590.         printf("Users for an unlocked reg!\n");
  1591.     break;
  1592.      case 1:
  1593.     if (lock_type == 2)
  1594.         printf("Locking shared reg for exclusive use!\n");
  1595.     break;
  1596.      case 2:
  1597.     printf("Locking exclusive reg!\n");
  1598.     break;
  1599.      default:
  1600.     printf("Unknown lock?\n");
  1601.     break;
  1602.     }
  1603. #endif
  1604.     map->x86_locked[x86r] = lock_type;
  1605.     map->x86_users[x86r]++;
  1606. }
  1607.  
  1608. static int get_and_lock_68k_reg(struct register_mapping *map, int reg, int is_dreg,
  1609.                 int preferred, int no_offset, int lock_type)
  1610. {
  1611.     int x86r;
  1612.     int *regmap;
  1613.     uae_u32 *reghome;
  1614.     uae_u32 const_off = 0;
  1615.  
  1616.     if (reg < 0 || reg > 7) {
  1617.     printf("Mad compiler disease\n");
  1618.     return 0;
  1619.     }
  1620.  
  1621.     if (is_dreg)
  1622.     regmap = map->dreg_map, reghome = regs.regs;
  1623.     else
  1624.     regmap = map->areg_map, reghome = regs.regs + 8;
  1625.  
  1626.     if (preferred == 0)
  1627.     preferred = ALL_X86_REGS;
  1628.  
  1629.     x86r = regmap[reg];
  1630.     if (x86r == -1) {
  1631.     x86r = get_free_x86_register(map, preferred);
  1632.     assemble(0x8B); assemble(0x05 + (x86r << 3)); /* movl regs.d[reg],x86r */
  1633.     assemble_long(reghome + reg);
  1634.     map->x86_cache_reg[x86r] = reg;
  1635.     map->x86_cr_type[x86r] = is_dreg;
  1636.     map->x86_const_offset[x86r] = 0;
  1637.     map->x86_dirty[x86r] = 0;
  1638.     map->x86_verified[x86r] = 0;
  1639.     map->x86_byteorder[x86r] = BO_NORMAL;
  1640.     regmap[reg] = x86r;
  1641.     } else {
  1642.     const_off = map->x86_const_offset[x86r];
  1643.  
  1644.     if (map->x86_locked[x86r] == 2
  1645.         || (map->x86_locked[x86r] == 1 && (lock_type == 2 || (const_off != 0 && no_offset))))
  1646.     {
  1647.         int newr;
  1648.         int old_dirty = 0;
  1649.         int old_verified;
  1650.         int old_bo;
  1651.  
  1652.         newr = get_free_x86_register(map, preferred);
  1653.         if (const_off == 0) {
  1654.         compile_move_reg_reg(newr, x86r, sz_long);
  1655.         } else {
  1656.         compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1657.         compile_lea_reg_with_offset(newr, x86r, const_off);
  1658.         old_dirty = 1;
  1659.         const_off = 0;
  1660.         }
  1661.         /* Remove old reg from cache... */
  1662.         map->x86_cache_reg[x86r] = -1;
  1663.         map->x86_cr_type[x86r] = is_dreg;
  1664.         map->x86_const_offset[x86r] = 0;
  1665.         old_dirty |= map->x86_dirty[x86r];
  1666.         old_verified = map->x86_verified[x86r];
  1667.         old_bo = map->x86_byteorder[x86r];
  1668.         map->x86_verified[x86r] = 0;
  1669.         map->x86_dirty[x86r] = 0;
  1670.         x86r = newr;
  1671.         /* ... and make the new one the cache register */
  1672.         map->x86_cache_reg[x86r] = reg;
  1673.         map->x86_cr_type[x86r] = is_dreg;
  1674.         map->x86_const_offset[x86r] = 0;
  1675.         map->x86_dirty[x86r] = old_dirty;
  1676.         map->x86_verified[x86r] = old_verified;
  1677.         map->x86_byteorder[x86r] = old_bo;
  1678.         regmap[reg] = x86r;
  1679.     }
  1680.     }
  1681.     if (no_offset && const_off != 0) {
  1682.     if (map->x86_locked[x86r] != 0)
  1683.         printf("modifying locked reg\n");
  1684.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1685.     compile_lea_reg_with_offset(x86r, x86r, map->x86_const_offset[x86r]);
  1686.     map->x86_const_offset[x86r] = 0;
  1687.     map->x86_dirty[x86r] = 1;
  1688.     }
  1689.     lock_reg(map, x86r, lock_type);
  1690.     return x86r;
  1691. }
  1692.  
  1693. /*
  1694.  * Move a constant to a register. Don't do anything if we already have a
  1695.  * register, even if it is offset by a constant
  1696.  */
  1697.  
  1698. static int compile_force_const_reg(struct register_mapping *map, int x86r,
  1699.                    uae_u32 *offs, int desired)
  1700. {
  1701.     int newr = x86r;
  1702.  
  1703.     if (newr == -2) {
  1704.     if (desired == 0)
  1705.         newr = get_free_x86_register(map, ALL_X86_REGS);
  1706.     else
  1707.         newr = get_typed_x86_register(map, desired);
  1708.  
  1709.     assemble(0xB8 + newr);
  1710.     assemble_ulong(*offs);
  1711.     *offs = 0;
  1712.     }
  1713.     map->x86_users[newr]++;
  1714.     return newr;
  1715. }
  1716.  
  1717. static void compile_extend_long(struct register_mapping *map, int x86r,
  1718.                 wordsizes size)
  1719. {
  1720.     if (x86r < 0) {
  1721.     printf("Bad reg in extend_long\n");
  1722.     return;
  1723.     }
  1724.  
  1725.     compile_force_byteorder(map, x86r, BO_NORMAL, 1);
  1726.  
  1727.     if (size != sz_long) {
  1728.     if (x86r == r_EAX && size == sz_word) {
  1729.         assemble(0x98); /* cwtl */
  1730.     } else {
  1731.         assemble(0x0F);
  1732.         if (size == sz_byte) {
  1733.         assemble(0xBE);
  1734.         } else {
  1735.         assemble(0xBF);
  1736.         }
  1737.         assemble(0xC0 + x86r*9);
  1738.     }
  1739.     }
  1740. }
  1741.  
  1742. struct ea_info {
  1743.     int reg;
  1744.     amodes mode;
  1745.     wordsizes size;
  1746.     int address_reg;    /* The x86 reg holding the address, or -1 if ea doesn't refer to memory
  1747.              * -2 if it refers to memory, but only with a constant address */
  1748.     uae_u32 addr_const_off; /* Constant offset to the address */
  1749.     int data_reg;         /* The x86 reg that holds the data. -1 if data is not present yet.
  1750.                * -2 if data is constant */
  1751.     uae_u32 data_const_off;
  1752.     int flags;            /* Extra info. Contains the dp field of d8r modes */
  1753.     int purpose;
  1754. };
  1755.  
  1756. static void init_eainfo(struct ea_info *eai)
  1757. {
  1758.     eai->address_reg = -1;
  1759.     eai->addr_const_off = 0;
  1760.     eai->data_reg = -1;
  1761.     eai->data_const_off = 0;
  1762. }
  1763.  
  1764. struct insn_reg_needs {
  1765.     int checkpoint_no;
  1766.     int dreg_needed[8], areg_needed[8];
  1767.     int dreg_mask[8], areg_mask[8];
  1768. };
  1769.  
  1770. /*
  1771.  * This structure holds information about predec/postinc addressing modes.
  1772.  */
  1773.  
  1774. struct pid_undo {
  1775.     int used;
  1776.     int x86r[2];
  1777.     int m68kr[2];
  1778.     int dirty[2];
  1779.     int offs[2];
  1780. };
  1781.  
  1782. static void add_undo(struct pid_undo *pud, int x86r, int m68kr, int offs,
  1783.              int dirty)
  1784. {
  1785.     int i;
  1786.     for (i = 0; i < pud->used; i++)
  1787.     if (pud->m68kr[i] == m68kr)
  1788.         return;
  1789.     pud->m68kr[i] = m68kr;
  1790.     pud->x86r[i] = x86r;
  1791.     pud->offs[i] = offs;
  1792.     pud->dirty[i] = dirty;
  1793.     pud->used++;
  1794. }
  1795.  
  1796. /*
  1797.  * Lock previous contents of address registers used in predec/postinc modes
  1798.  * for generate_possible_exit().
  1799.  */
  1800.  
  1801. static void compile_prepare_undo(struct register_mapping *map, amodes mode,
  1802.                   int reg, struct pid_undo *pud)
  1803. {
  1804.     int x86r;
  1805.  
  1806.     switch(mode){
  1807.      default:
  1808.     break;
  1809.  
  1810.      case Apdi:
  1811.     x86r = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1812.     /* This saves recording the byteorder in the pud structure, and we'll
  1813.      * need it in normal byteorder anyway */
  1814.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1815.     /*
  1816.      * Add this reg with its current offset to the undo buffer.
  1817.      * Since we have locked it, we are certain that it will not be
  1818.      * modified.
  1819.      */
  1820.     add_undo(pud, x86r, reg, map->x86_const_offset[x86r], map->x86_dirty[x86r]);
  1821.     break;
  1822.  
  1823.      case Aipi:
  1824.     x86r = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1825.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1826.     add_undo(pud, x86r, reg, map->x86_const_offset[x86r], map->x86_dirty[x86r]);
  1827.     break;
  1828.     }
  1829. }
  1830.  
  1831. /*
  1832.  * Load all the registers absolutely needed to calculate and verify thea
  1833.  * address. Load other registers if convenient.
  1834.  * This contains a fair amount of magic to get the register cache working right.
  1835.  */
  1836.  
  1837. static void compile_prepareea(struct register_mapping *map, amodes mode,
  1838.                   int reg, wordsizes size, uae_u8 **pcpp, uaecptr pca,
  1839.                   struct ea_info *eainf, int eaino, int ea_purpose,
  1840.                   int pidmult)
  1841. {
  1842.     struct ea_info *eai = eainf + eaino;
  1843.     int pdival = size == sz_byte && reg != 7 ? 1 : size == sz_long ? 4 : 2;
  1844.     uae_u8 *p = *pcpp;
  1845.     uae_u16 dp;
  1846.     int r;
  1847.     int x86r, tmpr;
  1848.  
  1849.     pdival *= pidmult;
  1850.  
  1851.     init_eainfo(eai);
  1852.     eai->mode = mode;
  1853.     eai->size = size;
  1854.     eai->reg = reg;
  1855.  
  1856.     switch(mode){
  1857.      case Dreg:
  1858.      case Areg:
  1859.     break;
  1860.  
  1861.      case Ad16:
  1862.     eai->addr_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1863.     (*pcpp) += 2; p += 2;
  1864.     x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1865.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1866.     eai->addr_const_off += map->x86_const_offset[x86r];
  1867.     break;
  1868.  
  1869.      case Aind:
  1870.     x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1871.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1872.     eai->addr_const_off = map->x86_const_offset[x86r];
  1873.     break;
  1874.  
  1875.      case Apdi:
  1876.     x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1877.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1878.     map->x86_const_offset[x86r] -= pdival;
  1879.     eai->addr_const_off = map->x86_const_offset[x86r];
  1880.     break;
  1881.  
  1882.      case Aipi:
  1883.     x86r = eai->address_reg = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1884.     compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1885.     eai->addr_const_off = map->x86_const_offset[x86r];
  1886.     map->x86_const_offset[x86r] += pdival;
  1887.     break;
  1888.  
  1889.      case Ad8r:
  1890.     dp = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1891.     r = (dp & 0x7000) >> 12;
  1892.     (*pcpp) += 2; p += 2;
  1893.  
  1894.     tmpr = get_and_lock_68k_reg(map, reg, 0, ADDRESS_X86_REGS, 0, 1);
  1895.     compile_force_byteorder(map, tmpr, BO_NORMAL, 0);
  1896.     eai->addr_const_off = map->x86_const_offset[tmpr] + (uae_s8)dp;
  1897.  
  1898.     if (dp & 0x800) {
  1899.         x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 0, 2);
  1900.         remove_x86r_from_cache(map, x86r, 0);
  1901.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1902.         eai->addr_const_off += map->x86_const_offset[x86r];
  1903.     } else {
  1904.         x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 1, 2);
  1905.         remove_x86r_from_cache(map, x86r, 0);
  1906.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1907.     }
  1908.     eai->address_reg = x86r;
  1909.  
  1910.     r = (dp & 0x7000) >> 12;
  1911.  
  1912.     if (dp & 0x800) {
  1913.         if (eai->addr_const_off == 0) {
  1914.         assemble(0x03); assemble(0xC0 + tmpr + x86r*8); /* addl basereg,addrreg */
  1915.         } else if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
  1916.         assemble(0x8D);
  1917.         assemble(0x44 + x86r*8); /* leal disp8(dispreg,basereg),dispreg */
  1918.         assemble(x86r*8 + tmpr);
  1919.         assemble(eai->addr_const_off);
  1920.         } else {
  1921.         assemble(0x8D);
  1922.         assemble(0x84 + x86r*8); /* leal disp32(dispreg,basereg),dispreg */
  1923.         assemble(x86r*8 + tmpr);
  1924.         assemble_ulong(eai->addr_const_off);
  1925.         }
  1926.         eai->addr_const_off = 0;
  1927.     } else {
  1928.         assemble(0x0F); assemble(0xBF);
  1929.         assemble(0xC0 + x86r*9); /* movswl dispreg,addrreg */
  1930.         assemble(0x03); assemble(0xC0 + tmpr + x86r*8); /* addl basereg,addrreg */
  1931.     }
  1932.     compile_unlock_reg(map, tmpr);
  1933.     break;
  1934.  
  1935.      case PC8r:
  1936.     dp = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1937.     (*pcpp) += 2; p += 2;
  1938.     r = (dp & 0x7000) >> 12;
  1939.     eai->addr_const_off = pca + (uae_s8)dp;
  1940.     if (dp & 0x800) {
  1941.         x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 0, 1);
  1942.         remove_x86r_from_cache(map, x86r, 0);
  1943.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1944.         eai->addr_const_off += map->x86_const_offset[x86r];
  1945.     } else {
  1946.         x86r = get_and_lock_68k_reg(map, r, dp & 0x8000 ? 0 : 1, ADDRESS_X86_REGS, 1, 2);
  1947.         remove_x86r_from_cache(map, x86r, 0);
  1948.         compile_force_byteorder(map, x86r, BO_NORMAL, 0);
  1949.  
  1950.         assemble(0x0F); assemble(0xBF);
  1951.         assemble(0xC0 + x86r*9); /* movswl dispreg,addrreg */
  1952.     }
  1953.     eai->address_reg = x86r;
  1954.     break;
  1955.  
  1956.      case PC16:
  1957.     eai->addr_const_off = pca + (uae_s16)do_get_mem_word((uae_u16 *)p);
  1958.     eai->address_reg = -2;
  1959.     (*pcpp) += 2; p += 2;
  1960.     break;
  1961.  
  1962.      case absw:
  1963.     eai->addr_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1964.     eai->address_reg = -2;
  1965.     (*pcpp) += 2; p += 2;
  1966.     break;
  1967.  
  1968.      case absl:
  1969.     eai->addr_const_off = (uae_s32)do_get_mem_long((uae_u32 *)p);
  1970.     eai->address_reg = -2;
  1971.     (*pcpp) += 4; p += 4;
  1972.     break;
  1973.  
  1974.      case imm:
  1975.     if (size == sz_long)
  1976.         goto imm2_const;
  1977.     if (size == sz_word)
  1978.         goto imm1_const;
  1979.  
  1980.     /* fall through */
  1981.      case imm0:
  1982.     eai->data_const_off = (uae_s8)*(p+1);
  1983.     eai->data_reg = -2;
  1984.     (*pcpp) += 2; p += 2;
  1985.     break;
  1986.  
  1987.      case imm1:
  1988.     imm1_const:
  1989.     eai->data_const_off = (uae_s16)do_get_mem_word((uae_u16 *)p);
  1990.     eai->data_reg = -2;
  1991.     (*pcpp) += 2; p += 2;
  1992.     break;
  1993.  
  1994.      case imm2:
  1995.     imm2_const:
  1996.     eai->data_const_off = (uae_s32)do_get_mem_long((uae_u32 *)p);
  1997.     eai->data_reg = -2;
  1998.     (*pcpp) += 4; p += 4;
  1999.     break;
  2000.  
  2001.      case immi:
  2002.     eai->data_const_off = (uae_s8)reg;
  2003.     eai->data_reg = -2;
  2004.     break;
  2005.  
  2006.      default:
  2007.     break;
  2008.     }
  2009.     eai->purpose = ea_purpose;
  2010. }
  2011.  
  2012. static void compile_get_excl_lock(struct register_mapping *map, struct ea_info *eai)
  2013. {
  2014.     int x86r = eai->data_reg;
  2015.  
  2016.     if (x86r >= 0 && map->x86_locked[x86r] == 1) {
  2017.     int newr;
  2018.     if (eai->size == sz_byte)
  2019.         newr = get_typed_x86_register(map, DATA_X86_REGS);
  2020.     else
  2021.         newr = get_free_x86_register(map, ALL_X86_REGS);
  2022.  
  2023.     compile_move_reg_reg(newr, x86r, sz_long);
  2024.     eai->data_reg = newr;
  2025.     lock_reg(map, eai->data_reg, 2);
  2026.     }
  2027. }
  2028.  
  2029. /*
  2030.  * Some functions to assemble some 386 opcodes which have a similar
  2031.  * structure (ADD, AND, OR, etc.). These take source and destination
  2032.  * addressing modes, check their validity and assemble a complete
  2033.  * 386 instruction.
  2034.  */
  2035.  
  2036. static __inline__ int rmop_long(struct ea_info *eai)
  2037. {
  2038.     if (eai->data_reg == -2)
  2039.     printf("rmop for const\n");
  2040.     else if (eai->data_reg == -1) {
  2041.     if (eai->address_reg == -2)
  2042.         return 5;
  2043.     if (eai->address_reg == -1) {
  2044.         /* This must be a 68k register in its home location */
  2045.         return 5;
  2046.     }
  2047. #if 0 /* We need to add address_space... */
  2048.     if (eai->addr_const_off == 0 && eai->address_reg != r_EBP) {
  2049.         return eai->address_reg;
  2050.     }
  2051.     else if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
  2052.         return eai->address_reg | 0x40;
  2053.     }
  2054. #endif
  2055.     return eai->address_reg | 0x80;
  2056.     } else {
  2057.     if (eai->size == sz_byte && ((1 << eai->data_reg) & DATA_X86_REGS) == 0)
  2058.         printf("wrong type reg in rmop\n");
  2059.     if (eai->data_const_off != 0)
  2060.         printf("data_const_off in rmop\n");
  2061.     return 0xC0 + eai->data_reg;
  2062.     }
  2063.     return 0;
  2064. }
  2065.  
  2066. static __inline__ int rmop_short(struct ea_info *eai)
  2067. {
  2068.     if (eai->data_reg == -2)
  2069.     printf("rmop_short for const\n");
  2070.     else if (eai->data_reg == -1) {
  2071.     printf("rmop_short for mem\n");
  2072.     } else {
  2073.     if (eai->size == sz_byte && ((1 << eai->data_reg) & DATA_X86_REGS) == 0)
  2074.         printf("wrong type reg in rmop_short\n");
  2075.     if (eai->data_const_off != 0)
  2076.         printf("data_const_off in rmop_short\n");
  2077.     return eai->data_reg*8;
  2078.     }
  2079.     return 0;
  2080. }
  2081.  
  2082. static __inline__ void rmop_finalize(struct ea_info *eai)
  2083. {
  2084.     if (eai->data_reg == -2)
  2085.     assemble_ulong(eai->data_const_off);
  2086.     else if (eai->data_reg == -1) {
  2087.     if (eai->address_reg == -2)
  2088.         /* Constant address */
  2089.         assemble_long(address_space + (uae_s32)eai->addr_const_off);
  2090.     else if (eai->address_reg == -1) {
  2091.         /* Register in its home location */
  2092.         if (eai->mode == Areg)
  2093.         assemble_long(regs.regs + 8  + eai->reg);
  2094.         else
  2095.         assemble_long(regs.regs + eai->reg);
  2096.     } else {
  2097. #if 0
  2098.         /* Indirect address with offset */
  2099.         if ((uae_s32)eai->addr_const_off >= -128 && (uae_s32)eai->addr_const_off <= 127) {
  2100.         }
  2101. #endif
  2102.         assemble_long(address_space + (uae_s32)eai->addr_const_off);
  2103.     }
  2104.     }
  2105. }
  2106.  
  2107. static void compile_eas(struct register_mapping *map, struct ea_info *eainf, int eaino_s, int eaino_d,
  2108.             int optype)
  2109. {
  2110.     struct ea_info *eais = eainf + eaino_s;
  2111.     struct ea_info *eaid = eainf + eaino_d;
  2112.     int szflag = eais->size == sz_byte ? 0 : 1;
  2113.     int swapflag = 0;
  2114.     int opcode;
  2115.  
  2116.     if (eais->data_reg == -1) {
  2117.     compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
  2118.     eais = eainf + eaino_d;
  2119.     eaid = eainf + eaino_s;
  2120.     swapflag = 1;
  2121.     }
  2122.     if (eais->data_reg == -1) {
  2123.     compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
  2124.     }
  2125.  
  2126.     if (eais->size == sz_word)
  2127.     assemble(0x66);
  2128.  
  2129.     if (eais->data_reg == -2) {
  2130.     assemble(0x80+szflag);
  2131.     assemble(8*optype | rmop_long(eaid));
  2132.     rmop_finalize(eaid);
  2133.     switch(eais->size) {
  2134.      case sz_byte: assemble(eais->data_const_off); break;
  2135.      case sz_word: assemble_uword(eais->data_const_off); break;
  2136.      case sz_long: assemble_ulong(eais->data_const_off); break;
  2137.     }
  2138.     } else {
  2139.     assemble(8*optype | szflag | 2*swapflag);
  2140.     assemble(rmop_long(eaid) | rmop_short(eais));
  2141.     rmop_finalize(eaid);
  2142.     }
  2143. }
  2144.  
  2145. static void compile_fetchmem(struct register_mapping *map, struct ea_info *eai)
  2146. {
  2147.     int x86r;
  2148.     if (eai->size == sz_byte)
  2149.     x86r = get_typed_x86_register(map, DATA_X86_REGS);
  2150.     else
  2151.     x86r = get_free_x86_register(map, ALL_X86_REGS);
  2152.  
  2153.     lock_reg(map, x86r, 2);
  2154.     compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
  2155.     compile_move_reg_from_mem_regoffs(x86r, eai->address_reg,
  2156.                       (uae_u32)(eai->addr_const_off + address_space),
  2157.                       eai->size);
  2158.     map->x86_verified[x86r] = 0;
  2159.     switch (eai->size) {
  2160.      case sz_byte: map->x86_byteorder[x86r] = BO_NORMAL; break;
  2161.      case sz_word: map->x86_byteorder[x86r] = BO_SWAPPED_WORD; break;
  2162.      case sz_long: map->x86_byteorder[x86r] = BO_SWAPPED_LONG; break;
  2163.     }
  2164.     eai->data_reg = x86r;
  2165.     eai->data_const_off = 0;
  2166. }
  2167.  
  2168. static void compile_fetchimm(struct register_mapping *map, struct ea_info *eai, int byteorder)
  2169. {
  2170.     int x86r;
  2171.     if (eai->size == sz_byte)
  2172.     x86r = get_typed_x86_register(map, DATA_X86_REGS);
  2173.     else
  2174.     x86r = get_free_x86_register(map, ALL_X86_REGS);
  2175.  
  2176.     switch (byteorder) {
  2177.      case BO_SWAPPED_LONG:
  2178.     eai->data_const_off = (((eai->data_const_off & 0xFF000000) >> 24)
  2179.                    | ((eai->data_const_off & 0xFF0000) >> 8)
  2180.                    | ((eai->data_const_off & 0xFF00) << 8)
  2181.                    | ((eai->data_const_off & 0xFF) << 24));
  2182.     break;
  2183.      case BO_SWAPPED_WORD:
  2184.     eai->data_const_off = (((eai->data_const_off & 0xFF00) >> 8)
  2185.                    | ((eai->data_const_off & 0xFF) << 8)
  2186.                    | (eai->data_const_off & 0xFFFF0000));
  2187.     break;
  2188.      case BO_NORMAL:
  2189.     break;
  2190.     }
  2191.     lock_reg(map, x86r, 2);
  2192.     map->x86_byteorder[x86r] = byteorder; map->x86_verified[x86r] = 0;
  2193.  
  2194.     switch (eai->size) {
  2195.      case sz_byte: assemble(0xC6); assemble(0xC0 + x86r); assemble(eai->data_const_off); break;
  2196.      case sz_word: assemble(0x66); assemble(0xC7); assemble(0xC0 + x86r); assemble_uword(eai->data_const_off); break;
  2197.      case sz_long: assemble(0xC7); assemble(0xC0 + x86r); assemble_ulong(eai->data_const_off); break;
  2198.     }
  2199.     eai->data_reg = x86r;
  2200.     eai->data_const_off = 0;
  2201. }
  2202.  
  2203. /*
  2204.  * 1: reg
  2205.  * 2: mem
  2206.  * 4: imm
  2207.  */
  2208.  
  2209. static int binop_alternatives[] = {
  2210.     7, 1,
  2211.     5, 3,
  2212.     0, 0
  2213. };
  2214.  
  2215. static int binop_worda_alternatives[] = {
  2216.     1, 3,
  2217.     0, 0
  2218. };
  2219.  
  2220. static int regonly_alternatives[] = {
  2221.     1, 1,
  2222.     0, 0
  2223. };
  2224.  
  2225. static void compile_loadeas(struct register_mapping *map, struct ea_info *eainf,
  2226.                int eaino_s, int eaino_d, int *alternatives,
  2227.                int scramble_poss, int load_dest)
  2228. {
  2229.     struct ea_info *eais = eainf + eaino_s;
  2230.     struct ea_info *eaid = eainf + eaino_d;
  2231.     int scrambled_bo = eaid->size == sz_long ? BO_SWAPPED_LONG : eaid->size == sz_word ? BO_SWAPPED_WORD : BO_NORMAL;
  2232.     int i, scrambled = 0;
  2233.     int best = 0;
  2234.     int bestcost = -1;
  2235.     int *ap;
  2236.     uae_u32 *sregp = NULL, *dregp = NULL;
  2237.     int screg = -1, dcreg = -1;
  2238.     int stype = -1, dtype = -1;
  2239.     int asrc, adst;
  2240.     int regprefs = eais->size == sz_byte ? DATA_X86_REGS : 0;
  2241.  
  2242.     if (eais->mode == Dreg) {
  2243.     stype = 0;
  2244.     screg = map->dreg_map[eais->reg];
  2245.     if (screg == -1)
  2246.         sregp = regs.regs + eais->reg;
  2247.     } else if (eais->mode == Areg) {
  2248.     stype = 0;
  2249.     screg = map->areg_map[eais->reg];
  2250.     if (screg == -1)
  2251.         sregp = regs.regs + 8 + eais->reg;
  2252.     } else if (eais->data_reg == -2) {
  2253.     stype = -2;
  2254.     }
  2255.  
  2256.     if (eaid->mode == Dreg) {
  2257.     dtype = 0;
  2258.     dcreg = map->dreg_map[eaid->reg];
  2259.     if (dcreg == -1)
  2260.         dregp = regs.regs + eaid->reg;
  2261.     } else if (eaid->mode == Areg) {
  2262.     dtype = 0;
  2263.     dcreg = map->areg_map[eaid->reg];
  2264.     if (dcreg == -1)
  2265.         dregp = regs.regs + 8 + eaid->reg;
  2266.     } else if (eaid->data_reg == -2) {
  2267.     dtype = -2;
  2268.     }
  2269.  
  2270.     ap = alternatives;
  2271.  
  2272.     for (i = 0;; i++) {
  2273.     int cost = 0;
  2274.  
  2275.     asrc = *ap++;
  2276.     if (asrc == 0)
  2277.         break;
  2278.     adst = *ap++;
  2279.  
  2280.     if (stype == -2 && (asrc & 4) == 0)
  2281.         cost++;
  2282.     else if (stype == -1 && ((asrc & 2) == 0 || (eais->size != sz_byte && !scramble_poss)))
  2283.         cost++;
  2284.     else if (stype == 0 && screg == -1 && (asrc & 2) == 0)
  2285.         cost++;
  2286.  
  2287.     if (dtype == -1 && ((adst & 2) == 0 || (eaid->size != sz_byte && !scramble_poss)))
  2288.         /* The !load_dest case isn't handled by the current code,
  2289.          * and it isn't desirable anyway. Use a different alternative
  2290.          */
  2291.         cost += load_dest ? 1 : 100;
  2292.     else if (dtype == 0 && dcreg == -1 && (adst & 2) == 0)
  2293.         cost++;
  2294.  
  2295.     if (bestcost == -1 || cost < bestcost) {
  2296.         bestcost = cost;
  2297.         best = i;
  2298.     }
  2299.     }
  2300.  
  2301.     asrc = alternatives[2*best];
  2302.     adst = alternatives[2*best+1];
  2303.  
  2304.     if (dtype == -1) {
  2305.     if (load_dest) {
  2306.         if ((adst & 2) == 0 || (eaid->size != sz_byte && !scramble_poss))
  2307.         compile_fetchmem(map, eaid);
  2308.     } else {
  2309.         if ((adst & 2) == 0) {
  2310.         printf("Not loading memory operand. Prepare to die.\n");
  2311.         if (eaid->size == sz_byte)
  2312.             eaid->data_reg = get_typed_x86_register(map, DATA_X86_REGS);
  2313.         else
  2314.             eaid->data_reg = get_free_x86_register(map, ALL_X86_REGS);
  2315.         }
  2316.     }
  2317.     /* Scrambled in both mem and reg cases */
  2318.     if (eaid->size != sz_byte && scramble_poss)
  2319.         scrambled = 1;
  2320.     } else {
  2321.     if (dcreg == -1 && !load_dest && (adst & 2) == 0 && eaid->size == sz_long) {
  2322.         /* We need a register, but we don't need to fetch the old data.
  2323.          * See storeea for some more code handling this case. This first
  2324.          * if statement could be eliminated, we would generate some
  2325.          * superfluous moves. This is an optimization. If it were not
  2326.          * done, the mem-mem-move warning could be commented in in
  2327.          * storeea. */
  2328.         if (eaid->size == sz_byte)
  2329.         eaid->data_reg = get_typed_x86_register(map, DATA_X86_REGS);
  2330.         else
  2331.         eaid->data_reg = get_free_x86_register(map, ALL_X86_REGS);
  2332.         eaid->data_const_off = 0;
  2333.     } else if ((dcreg == -1 && (adst & 2) == 0) || dcreg != -1) {
  2334.         int reg_bo;
  2335.         eaid->data_reg = get_and_lock_68k_reg(map, eaid->reg, eaid->mode == Dreg, regprefs, 1, 2);
  2336.         eaid->data_const_off = 0;
  2337.  
  2338.         reg_bo = map->x86_byteorder[eaid->data_reg];
  2339.  
  2340.         if (reg_bo != BO_NORMAL) {
  2341.         if (reg_bo != scrambled_bo)
  2342.             compile_force_byteorder(map, eaid->data_reg, BO_NORMAL, 0);
  2343.         else if (scramble_poss)
  2344.             scrambled = 1;
  2345.         }
  2346.     }
  2347.     }
  2348.  
  2349.     if (stype == -2) {
  2350.     /* @@@ may need to scramble imm, this is a workaround */
  2351.     if ((asrc & 4) == 0 || scrambled)
  2352.         compile_fetchimm(map, eais, scrambled ? scrambled_bo : BO_NORMAL);
  2353.     } else if (stype == -1) {
  2354.     if ((asrc & 2) == 0 || (eais->size != sz_byte && !scrambled))
  2355.         compile_fetchmem(map, eais);
  2356.     } else {
  2357.     if ((screg == -1 && (asrc & 2) == 0) || screg != -1) {
  2358.         eais->data_reg = get_and_lock_68k_reg(map, eais->reg, eais->mode == Dreg, regprefs, 1, 2);
  2359.         eais->data_const_off = 0;
  2360.     }
  2361.     }
  2362.  
  2363.     /* Optimization */
  2364.     if (scrambled && eais->data_reg >= 0 && !load_dest
  2365.     && map->x86_byteorder[eais->data_reg] == BO_NORMAL
  2366.     && eaid->size == sz_long && dtype == 0)
  2367.     scrambled = 0;
  2368.  
  2369.     if (regprefs != 0 && eais->data_reg >= 0 && ((1 << eais->data_reg) & regprefs) == 0) {
  2370.     int tmpr = get_typed_x86_register(map, regprefs);
  2371.     compile_move_reg_reg(tmpr, eais->data_reg, sz_long);
  2372.     eais->data_reg = tmpr;
  2373.     }
  2374.  
  2375.     if (regprefs != 0 && eaid->data_reg >= 0 && ((1 << eaid->data_reg) & regprefs) == 0) {
  2376.     int tmpr = get_typed_x86_register(map, regprefs);
  2377.     compile_move_reg_reg(tmpr, eaid->data_reg, sz_long);
  2378.     eaid->data_reg = tmpr;
  2379.     }
  2380.  
  2381.     /* Now set the byteorder once and for all (should already be correct for
  2382.      * most cases) */
  2383.     if (scrambled) {
  2384.     if (eaid->data_reg >= 0)
  2385.         compile_force_byteorder(map, eaid->data_reg, scrambled_bo, 0);
  2386.     if (eais->data_reg >= 0)
  2387.         compile_force_byteorder(map, eais->data_reg, scrambled_bo, 0);
  2388.     } else {
  2389.     if (eaid->data_reg >= 0)
  2390.         compile_force_byteorder(map, eaid->data_reg, BO_NORMAL, 0);
  2391.     if (eais->data_reg >= 0)
  2392.         compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 0);
  2393.     }
  2394. }
  2395.  
  2396. static void compile_fetchea(struct register_mapping *map, struct ea_info *eainf,
  2397.                 int eaino, int asrc)
  2398. {
  2399.     struct ea_info *eais = eainf + eaino;
  2400.     int scrambled_bo = eais->size == sz_long ? BO_SWAPPED_LONG : eais->size == sz_word ? BO_SWAPPED_WORD : BO_NORMAL;
  2401.     int i, scrambled = 0;
  2402.     int best = 0;
  2403.     int bestcost = -1;
  2404.     int *ap;
  2405.     uae_u32 *sregp = NULL;
  2406.     int screg = -1, stype = -1;
  2407.     int regprefs = eais->size == sz_byte ? DATA_X86_REGS : 0;
  2408.  
  2409.     if (eais->mode == Dreg) {
  2410.     stype = 0;
  2411.     screg = map->dreg_map[eais->reg];
  2412.     if (screg == -1)
  2413.         sregp = regs.regs + eais->reg;
  2414.     } else if (eais->mode == Areg) {
  2415.     stype = 0;
  2416.     screg = map->areg_map[eais->reg];
  2417.     if (screg == -1)
  2418.         sregp = regs.regs + 8 + eais->reg;
  2419.     } else if (eais->data_reg == -2) {
  2420.     stype = -2;
  2421.     }
  2422.  
  2423.     if (stype == -2) {
  2424.     if ((asrc & 4) == 0)
  2425.         compile_fetchimm(map, eais, scrambled ? scrambled_bo : BO_NORMAL);
  2426.     } else if (stype == -1) {
  2427.     if ((asrc & 2) == 0 || eais->size != sz_byte)
  2428.         compile_fetchmem(map, eais);
  2429.     } else {
  2430.     if ((screg == -1 && (asrc & 2) == 0) || screg != -1) {
  2431.         eais->data_reg = get_and_lock_68k_reg(map, eais->reg, eais->mode == Dreg, regprefs, 1, 2);
  2432.         eais->data_const_off = 0;
  2433.     }
  2434.     }
  2435.  
  2436.     if (eais->data_reg >= 0)
  2437.     compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 0);
  2438. }
  2439.  
  2440. /*
  2441.  * compile_note_modify() should be called on destination EAs obtained from
  2442.  * compile_loadeas(), if their value was modified (e.g. by the compile_eas()
  2443.  * function)
  2444.  */
  2445.  
  2446. static void compile_note_modify(struct register_mapping *map, struct ea_info *eainf,
  2447.                 int eaino)
  2448. {
  2449.     struct ea_info *eai = eainf + eaino;
  2450.     int newr;
  2451.     int szflag = eai->size == sz_byte ? 0 : 1;
  2452.  
  2453.     if (eai->mode == Dreg) {
  2454.     /* We only need to do something if we have the value in a register,
  2455.      * otherwise, the home location was modified already */
  2456.     if (eai->data_reg >= 0) {
  2457.         if (eai->data_reg != map->dreg_map[eai->reg]) {
  2458.         remove_x86r_from_cache(map, eai->data_reg, 0);
  2459.         if (map->dreg_map[eai->reg] >= 0)
  2460.             remove_x86r_from_cache(map, map->dreg_map[eai->reg], 0);
  2461.         map->x86_cache_reg[eai->data_reg] = eai->reg;
  2462.         map->x86_cr_type[eai->data_reg] = 1;
  2463.         map->dreg_map[eai->reg] = eai->data_reg;
  2464.         }
  2465.         map->x86_verified[eai->data_reg] = 0;
  2466.         map->x86_const_offset[eai->data_reg] = eai->data_const_off;
  2467.         map->x86_dirty[eai->data_reg] = 1;
  2468.     }
  2469.     return;
  2470.     } else if (eai->mode == Areg) {
  2471.     if (eai->size != sz_long)
  2472.         printf("Areg put != long\n");
  2473.  
  2474.     /* We only need to do something if we have the value in a register,
  2475.      * otherwise, the home location was modified already */
  2476.     if (eai->data_reg >= 0) {
  2477.         if (eai->data_reg != map->areg_map[eai->reg]) {
  2478.         remove_x86r_from_cache(map, eai->data_reg, 0);
  2479.         if (map->areg_map[eai->reg] >= 0)
  2480.             remove_x86r_from_cache(map, map->areg_map[eai->reg], 0);
  2481.         map->x86_cache_reg[eai->data_reg] = eai->reg;
  2482.         map->x86_cr_type[eai->data_reg] = 0;
  2483.         map->areg_map[eai->reg] = eai->data_reg;
  2484.         }
  2485.         map->x86_verified[eai->data_reg] = 0;
  2486.         map->x86_const_offset[eai->data_reg] = eai->data_const_off;
  2487.         map->x86_dirty[eai->data_reg] = 1;
  2488.     }
  2489.     return;
  2490.     } else {
  2491.     /* Storing to memory from reg? */
  2492.     if (eai->data_reg >= 0) {
  2493.         compile_offset_reg(map, eai->data_reg, eai->data_const_off);
  2494.  
  2495.         switch (eai->size) {
  2496.          case sz_byte: compile_force_byteorder(map, eai->data_reg, BO_NORMAL, 1); break;
  2497.          case sz_word: compile_force_byteorder(map, eai->data_reg, BO_SWAPPED_WORD, 1); break;
  2498.          case sz_long: compile_force_byteorder(map, eai->data_reg, BO_SWAPPED_LONG, 1); break;
  2499.         }
  2500.         compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
  2501.         compile_move_reg_to_mem_regoffs(eai->address_reg,
  2502.                         (uae_u32)(eai->addr_const_off + address_space),
  2503.                         eai->data_reg, eai->size);
  2504.     }
  2505.     }
  2506. }
  2507.  
  2508. static void compile_storeea(struct register_mapping *map, struct ea_info *eainf,
  2509.                 int eaino_s, int eaino_d)
  2510. {
  2511.     struct ea_info *eais = eainf + eaino_s;
  2512.     struct ea_info *eaid = eainf + eaino_d;
  2513.     int newr, cacher;
  2514.     int szflag = eaid->size == sz_byte ? 0 : 1;
  2515.  
  2516.     if (eaid->mode == Dreg) {
  2517.     /* Is the reg to move from already the register cache reg for the
  2518.      * destination? */
  2519.     if (eais->data_reg >= 0 && eais->data_reg == map->dreg_map[eaid->reg]) {
  2520.         map->x86_dirty[eais->data_reg] = 1; map->x86_verified[eais->data_reg] = 0;
  2521.         map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2522.         return;
  2523.     }
  2524.     /* Is the destination register in its home location? */
  2525.     if (map->dreg_map[eaid->reg] < 0) {
  2526.         if (eais->data_reg == -2) {
  2527.         /* Move immediate to regs.regs */
  2528.         if (eaid->size == sz_word) assemble(0x66);
  2529.         assemble(0xC6 + szflag); assemble(0x05); assemble_long(regs.regs + eaid->reg);
  2530.         switch (eaid->size) {
  2531.          case sz_byte: assemble(eais->data_const_off); break;
  2532.          case sz_word: assemble_uword(eais->data_const_off); break;
  2533.          case sz_long: assemble_ulong(eais->data_const_off); break;
  2534.         }
  2535.         } else if (eais->data_reg == -1) {
  2536. #if 0
  2537.         printf("Shouldn't happen (mem-mem-move)\n");
  2538. #endif
  2539.         /* This _can_ happen: move.l $4,d0, if d0 isn't in the
  2540.          * cache, will come here. But a reg will be allocated for
  2541.          * dest. We use this. This _really_ shouldn't happen if
  2542.          * the size isn't long. */
  2543.         if (eaid->size != sz_long)
  2544.             printf("_Really_ shouldn't happen (Dreg case)\n");
  2545.         map->x86_cache_reg[eaid->data_reg] = eaid->reg;
  2546.         map->x86_cr_type[eaid->data_reg] = 1;
  2547.         map->x86_const_offset[eaid->data_reg] = eaid->data_const_off;
  2548.         map->dreg_map[eaid->reg] = eaid->data_reg;
  2549.         map->x86_verified[eaid->data_reg] = 0;
  2550.         goto have_cache_reg_d;
  2551.         } else {
  2552.         if (eais->size == sz_long) {
  2553.             /* Make this the new register cache reg */
  2554.             remove_x86r_from_cache(map, eais->data_reg, 0);
  2555.             map->x86_cache_reg[eais->data_reg] = eaid->reg;
  2556.             map->x86_cr_type[eais->data_reg] = 1;
  2557.             map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2558.             map->dreg_map[eaid->reg] = eais->data_reg;
  2559.             map->x86_verified[eais->data_reg] = 0;
  2560.         } else {
  2561.             /* Move from reg to regs.regs */
  2562.             compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1);
  2563.             compile_offset_reg (map, eais->data_reg, eais->data_const_off);
  2564.             if (eaid->size == sz_word) assemble(0x66);
  2565.             assemble(0x88 + szflag); assemble(0x05 + 8*eais->data_reg);
  2566.             assemble_long(regs.regs + eaid->reg);
  2567.         }
  2568.         }
  2569.     } else {
  2570.         int destr;
  2571.  
  2572.         have_cache_reg_d:
  2573.  
  2574.         destr = map->dreg_map[eaid->reg];
  2575.         if (eaid->size != sz_long)
  2576.         compile_force_byteorder(map, destr, BO_NORMAL, 1);
  2577.  
  2578.         if (eais->data_reg == -2) {
  2579.         /* Move immediate to reg */
  2580.         if (eaid->size == sz_word) assemble(0x66);
  2581.         assemble(0xC6 + szflag); assemble(0xC0 + destr);
  2582.         switch (eaid->size) {
  2583.          case sz_byte: assemble(eais->data_const_off); break;
  2584.          case sz_word: assemble_uword(eais->data_const_off); break;
  2585.          case sz_long: assemble_ulong(eais->data_const_off); break;
  2586.         }
  2587.         /* normal byteorder comes either from force above or from long
  2588.          * const move */
  2589.         map->x86_byteorder[destr] = BO_NORMAL;
  2590.         } else if (eais->data_reg == -1) {
  2591.         if (eais->mode == Dreg) {
  2592.             compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + eais->reg),
  2593.                               eais->size);
  2594.             map->x86_byteorder[destr] = BO_NORMAL;
  2595.         } else if (eais->mode == Areg) {
  2596.             compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + 8 + eais->reg),
  2597.                               eais->size);
  2598.             map->x86_byteorder[destr] = BO_NORMAL;
  2599.         } else {
  2600.             /* Move mem to reg */
  2601.             compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
  2602.             compile_move_reg_from_mem_regoffs(destr, eais->address_reg,
  2603.                               (uae_u32)(eais->addr_const_off + address_space),
  2604.                               eais->size);
  2605.  
  2606.             switch (eais->size) {
  2607.              case sz_byte: map->x86_byteorder[destr] = BO_NORMAL; break;
  2608.              case sz_word: map->x86_byteorder[destr] = BO_SWAPPED_WORD; break;
  2609.              case sz_long: map->x86_byteorder[destr] = BO_SWAPPED_LONG; break;
  2610.             }
  2611.         }
  2612.         } else {
  2613.         if (eais->size == sz_long) {
  2614.             /* Make this the new register cache reg */
  2615.             remove_x86r_from_cache(map, eais->data_reg, 0);
  2616.             remove_x86r_from_cache(map, destr, 0);
  2617.             map->x86_cache_reg[eais->data_reg] = eaid->reg;
  2618.             map->x86_cr_type[eais->data_reg] = 1;
  2619.             map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2620.             map->dreg_map[eaid->reg] = eais->data_reg;
  2621.             map->x86_verified[eais->data_reg] = 0;
  2622.         } else {
  2623.             /* Move from reg to reg */
  2624.             compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1);
  2625.             compile_offset_reg (map, eais->data_reg, eais->data_const_off);
  2626.             if (eaid->size == sz_word) assemble(0x66);
  2627.             assemble(0x88 + szflag); assemble(0xC0 + destr + 8*eais->data_reg);
  2628.         }
  2629.         }
  2630.     }
  2631.  
  2632.     if (map->dreg_map[eaid->reg] >= 0)
  2633.         map->x86_dirty[map->dreg_map[eaid->reg]] = 1;
  2634.     return;
  2635.     } else if (eaid->mode == Areg) {
  2636.     if (eaid->size != sz_long)
  2637.         printf("Areg put != long\n");
  2638.  
  2639.     /* Is the reg to move from already the register cache reg for the
  2640.      * destination? */
  2641.     if (eais->data_reg >= 0 && eais->data_reg == map->areg_map[eaid->reg]) {
  2642.         map->x86_dirty[eais->data_reg] = 1; map->x86_verified[eais->data_reg] = 0;
  2643.         map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2644.         return;
  2645.     }
  2646.     /* Is the destination register in its home location? */
  2647.     if (map->areg_map[eaid->reg] < 0) {
  2648.         if (eais->data_reg == -2) {
  2649.         /* Move immediate to regs.regs */
  2650.         assemble(0xC7); assemble(0x05); assemble_long(regs.regs + 8 + eaid->reg);
  2651.         assemble_ulong(eais->data_const_off);
  2652.         } else if (eais->data_reg == -1) {
  2653. #if 0 /* see above... */
  2654.         printf("Shouldn't happen (mem-mem-move)\n");
  2655. #endif
  2656.         map->x86_cache_reg[eaid->data_reg] = eaid->reg;
  2657.         map->x86_cr_type[eaid->data_reg] = 0;
  2658.         map->x86_const_offset[eaid->data_reg] = eaid->data_const_off;
  2659.         map->areg_map[eaid->reg] = eaid->data_reg;
  2660.         map->x86_verified[eaid->data_reg] = 0;
  2661.         goto have_cache_reg_a;
  2662.         } else {
  2663.         /* Make this the new register cache reg */
  2664.         remove_x86r_from_cache(map, eais->data_reg, 0);
  2665.         map->x86_cache_reg[eais->data_reg] = eaid->reg;
  2666.         map->x86_cr_type[eais->data_reg] = 0;
  2667.         map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2668.         map->areg_map[eaid->reg] = eais->data_reg;
  2669.         map->x86_verified[eais->data_reg] = 0;
  2670.         }
  2671.     } else {
  2672.         int destr;
  2673.  
  2674.         have_cache_reg_a:
  2675.  
  2676.         destr = map->areg_map[eaid->reg];
  2677.         if (eaid->size != sz_long)
  2678.         compile_force_byteorder(map, destr, BO_NORMAL, 1);
  2679.  
  2680.         if (eais->data_reg == -2) {
  2681.         /* Move immediate to reg */
  2682.         assemble(0xC7); assemble(0xC0 + destr);
  2683.         assemble_ulong(eais->data_const_off);
  2684.  
  2685.         /* normal byteorder comes either from force above or from long
  2686.          * const move */
  2687.         map->x86_byteorder[destr] = BO_NORMAL;
  2688.         } else if (eais->data_reg == -1) {
  2689.         if (eais->mode == Dreg) {
  2690.             compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + eais->reg),
  2691.                               eais->size);
  2692.             map->x86_byteorder[destr] = BO_NORMAL;
  2693.         } else if (eais->mode == Areg) {
  2694.             compile_move_reg_from_mem_regoffs(destr, -2, (uae_u32)(regs.regs + 8 + eais->reg),
  2695.                               eais->size);
  2696.             map->x86_byteorder[destr] = BO_NORMAL;
  2697.         } else {
  2698.             /* Move mem to reg */
  2699.             compile_force_byteorder(map, eais->address_reg, BO_NORMAL, 0);
  2700.             compile_move_reg_from_mem_regoffs(destr, eais->address_reg,
  2701.                               (uae_u32)(eais->addr_const_off + address_space),
  2702.                               eais->size);
  2703.  
  2704.             map->x86_byteorder[destr] = BO_SWAPPED_LONG;
  2705.         }
  2706.         } else {
  2707.         /* Make this the new register cache reg */
  2708.         remove_x86r_from_cache(map, eais->data_reg, 0);
  2709.         remove_x86r_from_cache(map, destr, 0);
  2710.         map->x86_cache_reg[eais->data_reg] = eaid->reg;
  2711.         map->x86_cr_type[eais->data_reg] = 0;
  2712.         map->x86_const_offset[eais->data_reg] = eais->data_const_off;
  2713.         map->areg_map[eaid->reg] = eais->data_reg;
  2714.         map->x86_verified[eais->data_reg] = 0;
  2715.         }
  2716.     }
  2717.  
  2718.     if (map->areg_map[eaid->reg] >= 0)
  2719.         map->x86_dirty[map->areg_map[eaid->reg]] = 1;
  2720.     return;
  2721.     }
  2722.  
  2723.     if (eais->data_reg == -1)
  2724.     printf("Storing to mem, but not from reg\n");
  2725.     /* Correct the byteorder */
  2726.     if (eais->data_reg != -2) {
  2727.     compile_offset_reg(map, eais->data_reg, eais->data_const_off);
  2728.  
  2729.     switch (eaid->size) {
  2730.      case sz_byte: compile_force_byteorder(map, eais->data_reg, BO_NORMAL, 1); break;
  2731.      case sz_word: compile_force_byteorder(map, eais->data_reg, BO_SWAPPED_WORD, 1); break;
  2732.      case sz_long: compile_force_byteorder(map, eais->data_reg, BO_SWAPPED_LONG, 1); break;
  2733.     }
  2734.     compile_force_byteorder(map, eaid->address_reg, BO_NORMAL, 0);
  2735.     compile_move_reg_to_mem_regoffs(eaid->address_reg,
  2736.                     (uae_u32)(eaid->addr_const_off + address_space),
  2737.                     eais->data_reg, eaid->size);
  2738.     } else {
  2739.     switch (eaid->size) {
  2740.      case sz_long:
  2741.         eais->data_const_off = (((eais->data_const_off & 0xFF000000) >> 24)
  2742.                  | ((eais->data_const_off & 0xFF0000) >> 8)
  2743.                  | ((eais->data_const_off & 0xFF00) << 8)
  2744.                  | ((eais->data_const_off & 0xFF) << 24));
  2745.         break;
  2746.      case sz_word:
  2747.         eais->data_const_off = (((eais->data_const_off & 0xFF00) >> 8)
  2748.                  | ((eais->data_const_off & 0xFF) << 8));
  2749.         break;
  2750.     }
  2751.     compile_force_byteorder(map, eaid->address_reg, BO_NORMAL, 0);
  2752.     /* generate code to move valueoffset,eaoffset(eareg) */
  2753.     switch(eaid->size) {
  2754.      case sz_byte: assemble(0xC6); break;
  2755.      case sz_word: assemble(0x66); /* fall through */
  2756.      case sz_long: assemble(0xC7); break;
  2757.     }
  2758.     if (eaid->address_reg == -2) { /* absolute or PC-relative */
  2759.         assemble(0x05);
  2760.         assemble_long(eaid->addr_const_off + address_space);
  2761.     } else {
  2762.         assemble(0x80 + eaid->address_reg);
  2763.         assemble_long(eaid->addr_const_off + address_space);
  2764.     }
  2765.     switch(eaid->size) {
  2766.      case sz_byte: assemble(eais->data_const_off); break;
  2767.      case sz_word: assemble_uword(eais->data_const_off); break;
  2768.      case sz_long: assemble_ulong(eais->data_const_off); break;
  2769.     }
  2770.     }
  2771. }
  2772.  
  2773. #define CE_STACK_SIZE 1000
  2774.  
  2775. static struct {
  2776.     struct register_mapping map;
  2777.     char *jmpoffs;
  2778.     uae_u32 address;
  2779.     int noflush:1;
  2780. } compile_exit_stack[CE_STACK_SIZE];
  2781.  
  2782. static int cesp;
  2783.  
  2784. static struct register_mapping current_exit_regmap;
  2785.  
  2786. static void generate_exit(struct register_mapping *map, int address)
  2787. {
  2788.     int i;
  2789.  
  2790.     if (map != NULL)
  2791.     sync_reg_cache (map, 1);
  2792.     assemble(0xB8); /* movl $new_pc,%eax */
  2793.     assemble_ulong(address);
  2794.     assemble(0xC3); /* RET */
  2795. }
  2796.  
  2797. static void copy_map_with_undo(struct register_mapping *dst,
  2798.                    struct register_mapping *src,
  2799.                    struct pid_undo *pud)
  2800. {
  2801.     int i;
  2802.     *dst = *src;
  2803.     for (i = 0; i < pud->used; i++) {
  2804.     int m68kr = pud->m68kr[i];
  2805.     int x86r = pud->x86r[i];
  2806.     int old_cr = dst->areg_map[m68kr];
  2807.     if (old_cr != -1) {
  2808.         dst->x86_cache_reg[old_cr] = -1;
  2809.     }
  2810.     dst->x86_cache_reg[x86r] = m68kr;
  2811.     dst->areg_map[m68kr] = x86r;
  2812.     dst->x86_cr_type[x86r] = 0;
  2813.     dst->x86_const_offset[x86r] = pud->offs[i];
  2814.     dst->x86_dirty[x86r] = pud->dirty[i];
  2815.     }
  2816. }
  2817.  
  2818. static void unlock_pud(struct register_mapping *map, struct pid_undo *pud)
  2819. {
  2820.     int i;
  2821.     for (i = 0; i < pud->used; i++) {
  2822.     compile_unlock_reg(map, pud->x86r[i]);
  2823.     }
  2824. }
  2825.  
  2826. static int exits_necessary;
  2827.  
  2828. static void generate_possible_exit(struct register_mapping *map,
  2829.                    struct ea_info *eai, int iip,
  2830.                    struct pid_undo *pud)
  2831. {
  2832.     struct register_mapping exit_regmap;
  2833.  
  2834.     if (!exits_necessary) {
  2835.     unlock_pud(map, pud);
  2836.     return;
  2837.     }
  2838.  
  2839.     compile_force_byteorder(map, eai->address_reg, BO_NORMAL, 0);
  2840.     switch (eai->address_reg) {
  2841.      case -1:
  2842.     /* EA doesn't refer to memory */
  2843.     break;
  2844.      case -2:
  2845.     /* Only a constant offset */
  2846.     eai->addr_const_off &= (1<<24)-1;
  2847.     if (!good_address_map[eai->addr_const_off]) {
  2848.         copy_map_with_undo(&exit_regmap, map, pud);
  2849.         generate_exit(&exit_regmap, insn_info[iip].address);
  2850.     }
  2851.     break;
  2852.      default:
  2853.     if (map->x86_verified[eai->address_reg])
  2854.         break;
  2855.     map->x86_verified[eai->address_reg] = 1;
  2856.     if (cesp == CE_STACK_SIZE) {
  2857.         copy_map_with_undo(&exit_regmap, map, pud);
  2858.         generate_exit(&exit_regmap, insn_info[iip].address);
  2859.         break;
  2860.     }
  2861.     copy_map_with_undo(&compile_exit_stack[cesp].map, map, pud);
  2862.     compile_exit_stack[cesp].address = insn_info[iip].address;
  2863.     assemble(0x80); assemble(0xB8 + eai->address_reg); /* cmpb $0, good_address_map(x86r) */
  2864.     assemble_long(good_address_map + eai->addr_const_off);
  2865.     assemble(0);
  2866.     assemble(0x0F); assemble(0x84); /* JE finish */
  2867.     compile_exit_stack[cesp].jmpoffs = compile_here();
  2868.     compile_exit_stack[cesp].noflush = 0;
  2869.     assemble_ulong(0);
  2870.     cesp++;
  2871.     break;
  2872.     }
  2873.     unlock_pud(map, pud);
  2874. }
  2875.  
  2876. static void finish_exits(void)
  2877. {
  2878.     int i;
  2879.     for (i = 0; i < cesp; i++) {
  2880.     char *exitpoint = compile_here();
  2881.     char *nextpoint;
  2882.  
  2883.     if (compile_exit_stack[i].noflush)
  2884.         generate_exit(NULL, compile_exit_stack[i].address);
  2885.     else
  2886.         generate_exit(&compile_exit_stack[i].map, compile_exit_stack[i].address);
  2887.     nextpoint = compile_here();
  2888.     compile_org(compile_exit_stack[i].jmpoffs);
  2889.     assemble_ulong(exitpoint - (compile_exit_stack[i].jmpoffs + 4));
  2890.     compile_org(nextpoint);
  2891.     }
  2892. }
  2893.  
  2894. static void finish_condjumps(int lastiip)
  2895. {
  2896.     int iip;
  2897.     char *lastptr = compile_here();
  2898.     for (iip = 0; iip < lastiip; iip++) {
  2899.     char *fillin = insn_info[iip].compiled_fillin;
  2900.     if (fillin != NULL) {
  2901.         compile_org(insn_info[iip].compiled_fillin);
  2902.         assemble_ulong(insn_info[insn_info[iip].jumps_to].compiled_jumpaddr - (fillin + 4));
  2903.     }
  2904.     }
  2905.     compile_org(lastptr);
  2906. }
  2907.  
  2908. #define CC_X_FROM_86C 1
  2909. #define CC_C_FROM_86C 2
  2910. #define CC_Z_FROM_86Z 4
  2911. #define CC_V_FROM_86V 8
  2912. #define CC_N_FROM_86N 16
  2913. #define CC_TEST_REG   32
  2914. #define CC_Z_FROM_86C 64
  2915. #define CC_SAHF       128
  2916. #define CC_TEST_CONST 256
  2917. #define CC_AFTER_RO   512
  2918. #define CC_AFTER_ROX  1024
  2919.  
  2920. static unsigned int cc_status;
  2921. static int cc_reg;
  2922. static uae_u32 cc_offset;
  2923. static wordsizes cc_size;
  2924.  
  2925. static void compile_do_cc_test_reg(struct register_mapping *map)
  2926. {
  2927.     compile_force_byteorder(map, cc_reg, BO_NORMAL, 1);
  2928.     if (cc_offset != 0)
  2929.     printf("Pull my finger\n");
  2930.     if (cc_size == sz_word) /* test ccreg */
  2931.     assemble(0x66);
  2932.     if (cc_size == sz_byte)
  2933.     assemble(0x84);
  2934.     else
  2935.     assemble(0x85);
  2936.     assemble(0xC0 + 9*cc_reg);
  2937. }
  2938.  
  2939. static int compile_flush_cc_cache(struct register_mapping *map, int status,
  2940.                   int live_at_end, int user_follows,
  2941.                   int user_live_at_end, int user_ccval)
  2942. {
  2943.     int status_for_user = 0;
  2944.  
  2945.     if (user_follows) {
  2946.     int need_for_user = 0;
  2947.     int user_flagmask = cc_flagmask_68k(user_ccval);
  2948.  
  2949.     if (user_flagmask & CC68K_C)
  2950.         need_for_user |= CC_C_FROM_86C;
  2951.     if (user_flagmask & CC68K_Z)
  2952.         need_for_user |= CC_Z_FROM_86Z;
  2953.     if (user_flagmask & CC68K_N)
  2954.         need_for_user |= CC_N_FROM_86N;
  2955.     if (user_flagmask & CC68K_V)
  2956.         need_for_user |= CC_V_FROM_86V;
  2957.  
  2958.     /* Check whether we can satisfy the user's needs in a simple way. */
  2959.     if ((need_for_user & status) == need_for_user)
  2960.         status_for_user = status;
  2961.     else if (user_flagmask == CC68K_Z && status == CC_Z_FROM_86C)
  2962.         status_for_user = status;
  2963.     else if (status == CC_TEST_REG && (user_flagmask & (CC68K_C|CC68K_V|CC68K_Z|CC68K_N)) != 0) {
  2964.         if (cc_reg == -2) {
  2965.         status_for_user = CC_TEST_CONST;
  2966.         } else {
  2967.         compile_do_cc_test_reg(map);
  2968.         status_for_user = status = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2969.         }
  2970.     } else if (status == CC_AFTER_RO) {
  2971.         /* We fake some information here... */
  2972.         if (user_flagmask == CC68K_C && (user_live_at_end & ~CC68K_C) == 0)
  2973.         status = status_for_user = CC_C_FROM_86C;
  2974.         else if (((user_flagmask | user_live_at_end) & (CC68K_C|CC68K_V)) == 0) {
  2975.         status = CC_TEST_REG; user_live_at_end = CC68K_Z|CC68K_N|CC68K_V;
  2976.         status_for_user = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2977.         } else
  2978.         status_for_user = CC_SAHF;
  2979.     } else if (status == CC_AFTER_ROX) {
  2980.         if (user_flagmask == CC68K_C && (user_live_at_end & ~(CC68K_C|CC68K_X)) == 0)
  2981.         status = status_for_user = CC_C_FROM_86C;
  2982.         else if (((user_flagmask | user_live_at_end) & (CC68K_C|CC68K_X|CC68K_V)) == 0) {
  2983.         status = CC_TEST_REG; user_live_at_end = CC68K_Z|CC68K_N|CC68K_V;
  2984.         status_for_user = (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V);
  2985.         } else
  2986.         status_for_user = CC_SAHF;
  2987.     } else if (need_for_user != 0) {
  2988.         /* No way to handle it easily */
  2989.         status_for_user = CC_SAHF;
  2990.     }
  2991.     if (status_for_user != CC_SAHF)
  2992.         live_at_end = user_live_at_end;
  2993.     }
  2994.  
  2995.     /*
  2996.      * Now store the flags which are live at the end of this insn and set by
  2997.      * us into their home locations
  2998.      */
  2999.     if (status == CC_TEST_REG) {
  3000.     if ((live_at_end & (CC68K_C|CC68K_V|CC68K_Z|CC68K_N)) == 0)
  3001.         goto all_ok;
  3002.  
  3003.     if (cc_reg == -2) {
  3004.         uae_u8 f = 0;
  3005.         if (cc_size == sz_byte) {
  3006.         f |= (cc_offset & 0x80) ? 0x80 : 0;
  3007.         f |= (cc_offset & 0xFF) == 0 ? 0x40 : 0;
  3008.         } else if (cc_size == sz_byte) {
  3009.         f |= (cc_offset & 0x8000) ? 0x80 : 0;
  3010.         f |= (cc_offset & 0xFFFF) == 0 ? 0x40 : 0;
  3011.         } else {
  3012.         f |= (cc_offset & 0x80000000) ? 0x80 : 0;
  3013.         f |= (cc_offset & 0xFFFFFFFF) == 0 ? 0x40 : 0;
  3014.         }
  3015.         assemble(0xC7); assemble(0x05);
  3016.         assemble_long((char*)®flags);
  3017.         assemble_uword(f);
  3018.     } else {
  3019.         int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  3020.         compile_do_cc_test_reg(map);
  3021.  
  3022.         /* pushfl; popl tmpr; movl tempr, regflags */
  3023.         assemble(0x9C); assemble(0x58+tmpr);
  3024.         compile_move_reg_to_mem_regoffs(-2, (uae_u32)®flags, tmpr, sz_long);
  3025.     }
  3026.     } else if (status == CC_Z_FROM_86C) {
  3027.     if ((live_at_end & CC68K_Z) != 0) {
  3028.         int tmpr = get_typed_x86_register(map, DATA_X86_REGS);
  3029.         assemble(0x9C);
  3030.         /* setnc tmpr; shl $6, tmpr; andb $~0x40, regflags; orb tmpr, regflags */
  3031.         assemble(0x0F); assemble(0x93); assemble(0xC0 + tmpr);
  3032.         assemble(0xC0); assemble(4*8 + 0xC0 + tmpr); assemble(6);
  3033.         assemble(0x80); assemble(0x05+0x20); assemble_long(®flags); assemble((uae_u8)~0x40);
  3034.         assemble(0x08); assemble(0x05+ tmpr*8); assemble_long(®flags);
  3035.         assemble(0x9D);
  3036.     }
  3037.     } else if (status == CC_AFTER_RO || status == CC_AFTER_ROX) {
  3038.     int tmpr = get_typed_x86_register(map, DATA_X86_REGS);
  3039.     assemble(0x9C);
  3040.     compile_do_cc_test_reg(map);
  3041.     /* pushfl; popl tmpr; andl $0xff,tmpr (mask out V flag which is cleared after rotates) */
  3042.     assemble(0x9C); assemble(0x58 + tmpr);
  3043.     assemble(0x81); assemble(0xC0 + tmpr + 8*4); assemble_ulong(0xFF);
  3044.     assemble(0x9D);
  3045.     /* adc $0, tmpr */
  3046.     assemble(0x80); assemble(0xC0 + tmpr + 8*2); assemble(0);
  3047.     compile_move_reg_to_mem_regoffs(-2, (uae_u32)®flags, tmpr, sz_long);
  3048.     if (status == CC_AFTER_ROX)
  3049.         compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)®flags, tmpr, sz_long);
  3050.     } else if (status != 0) {
  3051.     assert((status & CC_TEST_REG) == 0);
  3052.     assert (status == (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_X_FROM_86C | CC_V_FROM_86V)
  3053.         || status == (CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V)
  3054.         || status == CC_C_FROM_86C);
  3055.  
  3056.     if ((status & CC_X_FROM_86C) == 0)
  3057.         live_at_end &= ~CC68K_X;
  3058.  
  3059.     if (status == CC_C_FROM_86C && (live_at_end & CC68K_C) != 0)
  3060.         fprintf(stderr, "Shouldn't be needing C here!\n");
  3061.     else if (live_at_end) {
  3062.         if ((live_at_end & CC68K_X) == 0)
  3063.         status &= ~CC_X_FROM_86C;
  3064.  
  3065.         if (live_at_end) {
  3066.         if ((status & CC_X_FROM_86C) != 0 && live_at_end == CC68K_X) {
  3067.             /* SETC regflags + 4 */
  3068.             assemble(0x0F); assemble(0x92);
  3069.             assemble(0x05); assemble_long(4 + (uae_u32)®flags);
  3070.         } else {
  3071.             int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  3072.             /* pushfl; popl tmpr; movl tempr, regflags */
  3073.             assemble(0x9C); assemble(0x58+tmpr);
  3074.             compile_move_reg_to_mem_regoffs(-2, (uae_u32)®flags, tmpr, sz_long);
  3075.  
  3076.             if (status & CC_X_FROM_86C) {
  3077.             compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)®flags, tmpr, sz_word);
  3078.             }
  3079.         }
  3080.         }
  3081.     }
  3082.     }
  3083.  
  3084.     all_ok:
  3085.     return status_for_user;
  3086. }
  3087.  
  3088. static char *compile_condbranch(struct register_mapping *map, int iip,
  3089.                 int new_cc_status)
  3090. {
  3091.     int cc = insn_info[iip].dp->cc;
  3092.     int flagsused = cc_flagmask_68k(cc);
  3093.     int flagsneeded = 0;
  3094.     char *undo_pointer = compile_here();
  3095.  
  3096.     if (flagsused & CC68K_C)
  3097.     flagsneeded |= CC_C_FROM_86C;
  3098.     if (flagsused & CC68K_Z)
  3099.     flagsneeded |= CC_Z_FROM_86Z;
  3100.     if (flagsused & CC68K_N)
  3101.     flagsneeded |= CC_N_FROM_86N;
  3102.     if (flagsused & CC68K_V)
  3103.     flagsneeded |= CC_V_FROM_86V;
  3104.  
  3105.     if (flagsneeded == 0)
  3106.     /* Fine */;
  3107.     else if (new_cc_status == CC_SAHF) {
  3108.     int tmpr = get_free_x86_register(map, ALL_X86_REGS);
  3109.     compile_move_reg_from_mem_regoffs(tmpr, -2, (uae_u32)®flags, sz_long);
  3110.     assemble(0x66); assemble(0x50+tmpr); assemble(0x66); assemble(0x9D);
  3111.     new_cc_status = CC_C_FROM_86C|CC_Z_FROM_86Z|CC_N_FROM_86N|CC_V_FROM_86V;
  3112.     } else if (new_cc_status == CC_TEST_CONST) {
  3113.     int n,z;
  3114.     switch(cc_size) {
  3115.      case sz_byte: n = ((uae_s8)cc_offset) < 0; z = ((uae_s8)cc_offset) == 0; break;
  3116.      case sz_word: n = ((uae_s16)cc_offset) < 0; z = ((uae_s16)cc_offset) == 0; break;
  3117.      case sz_long: n = ((uae_s32)cc_offset) < 0; z = ((uae_s32)cc_offset) == 0; break;
  3118.     }
  3119. #define Bcc_TRUE 0
  3120. #define Bcc_FALSE 1
  3121.     flagsneeded = 0;
  3122.     new_cc_status = 0;
  3123.     switch (cc) {
  3124.      case 2: cc = !z ? Bcc_TRUE : Bcc_FALSE; break; /* !CFLG && !ZFLG */
  3125.      case 3: cc = z ? Bcc_TRUE : Bcc_FALSE; break; /* CFLG || ZFLG */
  3126.      case 4: cc = Bcc_TRUE; break; /* !CFLG */
  3127.      case 5: cc = Bcc_FALSE; break; /* CFLG */
  3128.      case 6: cc = !z ? Bcc_TRUE : Bcc_FALSE; break; /* !ZFLG */
  3129.      case 7: cc = z ? Bcc_TRUE : Bcc_FALSE; break; /* ZFLG */
  3130.      case 8: cc = Bcc_TRUE; break; /* !VFLG */
  3131.      case 9: cc = Bcc_FALSE; break; /* VFLG */
  3132.      case 10:cc = !n ? Bcc_TRUE : Bcc_FALSE; break; /* !NFLG */
  3133.      case 11:cc = n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG */
  3134.      case 12:cc = !n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG == VFLG */
  3135.      case 13:cc = n ? Bcc_TRUE : Bcc_FALSE; break; /* NFLG != VFLG */
  3136.      case 14:cc = !n && !z ? Bcc_TRUE : Bcc_FALSE; break; /* !ZFLG && (NFLG == VFLG) */
  3137.      case 15:cc = n || z ? Bcc_TRUE : Bcc_FALSE; break; /* ZFLG || (NFLG != VFLG) */
  3138.     }
  3139.     } else if (new_cc_status == CC_Z_FROM_86C) {
  3140.     if (cc == 6 || cc == 7) {
  3141.         cc = (cc - 2) ^ 1;
  3142.         /* Fake... */
  3143.         flagsneeded = new_cc_status = CC_C_FROM_86C;
  3144.     } else if (cc != 0 && cc != 1)
  3145.         printf("Groan!\n");
  3146.     }
  3147.  
  3148.     if (cc == 1)
  3149.     return NULL;
  3150.  
  3151.     if ((flagsneeded & new_cc_status) == flagsneeded) {
  3152.     char *result;
  3153.     /* We can generate a simple branch */
  3154.     if (cc == 0)
  3155.         assemble(0xE9);
  3156.     else
  3157.         assemble(0x0F);
  3158.     switch(cc) {
  3159.      case 2: assemble(0x87); break;          /* HI */
  3160.      case 3: assemble(0x86); break;          /* LS */
  3161.      case 4: assemble(0x83); break;          /* CC */
  3162.      case 5: assemble(0x82); break;          /* CS */
  3163.      case 6: assemble(0x85); break;          /* NE */
  3164.      case 7: assemble(0x84); break;          /* EQ */
  3165.      case 8: assemble(0x81); break;          /* VC */
  3166.      case 9: assemble(0x80); break;          /* VS */
  3167.      case 10:assemble(0x89); break;          /* PL */
  3168.      case 11:assemble(0x88); break;          /* MI */
  3169.      case 12:assemble(0x8D); break;          /* GE */
  3170.      case 13:assemble(0x8C); break;          /* LT */
  3171.      case 14:assemble(0x8F); break;          /* GT */
  3172.      case 15:assemble(0x8E); break;          /* LE */
  3173.     }
  3174.     result = compile_here();
  3175.     assemble_ulong(0);
  3176.     return result;
  3177.     }
  3178.     printf("Uhhuh.\n");
  3179.     return NULL;
  3180. }
  3181.  
  3182. static void compile_handle_bcc(struct register_mapping *map, int iip,
  3183.                    int new_cc_status)
  3184. {
  3185.     insn_info[iip].compiled_fillin = compile_condbranch(map, iip, new_cc_status);
  3186. }
  3187.  
  3188. static void compile_handle_dbcc(struct register_mapping *map, int iip,
  3189.                 int new_cc_status, int dreg)
  3190. {
  3191.     char *fillin1 = compile_condbranch(map, iip, new_cc_status);
  3192.  
  3193.     /* subw $1,dreg; jnc ... */
  3194.     assemble(0x66); assemble(0x83); assemble(0x05 + 5*8);
  3195.     assemble_long(regs.regs + dreg);
  3196.     assemble(1);
  3197.     assemble(0x0F); assemble(0x83);
  3198.     insn_info[iip].compiled_fillin = compile_here();
  3199.     assemble_ulong(0);
  3200.     if (fillin1 != NULL) {
  3201.     char *oldp = compile_here();
  3202.     compile_org(fillin1);
  3203.     assemble_ulong(oldp - (fillin1+4));
  3204.     compile_org(oldp);
  3205.     }
  3206. }
  3207.  
  3208. static void handle_bit_insns(struct register_mapping *map, struct ea_info *eainf,
  3209.                  int eaino_s, int eaino_d, instrmnem optype)
  3210. {
  3211.     struct ea_info *srcea = eainf + eaino_s, *dstea = eainf + eaino_d;
  3212.     int code = (optype == i_BTST ? 0
  3213.         : optype == i_BSET ? 1
  3214.         : optype == i_BCLR ? 2
  3215.         : /* optype == i_BCHG */ 3);
  3216.  
  3217.     compile_fetchea(map, eainf, eaino_s, 5);
  3218.     compile_fetchea(map, eainf, eaino_d, 3);
  3219.  
  3220.     if (srcea->data_reg != -2) {
  3221.     compile_force_byteorder(map, srcea->data_reg, BO_NORMAL, 0);
  3222.     remove_x86r_from_cache(map, srcea->data_reg, 0);
  3223.     /* andl $something,srcreg */
  3224.     assemble(0x83); assemble(0xC0 + 4*8 + srcea->data_reg);
  3225.     if (dstea->size == sz_byte)
  3226.         assemble(7);
  3227.     else
  3228.         assemble(31);
  3229.     } else
  3230.     if (dstea->size == sz_byte)
  3231.         srcea->data_const_off &= 7;
  3232.     else
  3233.         srcea->data_const_off &= 31;
  3234.  
  3235.     /* Areg isn't possible here */
  3236.     if (dstea->mode == Dreg && dstea->data_reg == -1) {
  3237.     if (srcea->data_reg == -2) {
  3238.         assemble(0x0F); assemble(0xBA); assemble(5 + 8*(4 + code));
  3239.         assemble_long(regs.regs + dstea->reg);
  3240.         assemble(srcea->data_const_off);
  3241.     } else {
  3242.         assemble(0x0F); assemble(0xA3 + 8*code);
  3243.         assemble(5 + srcea->data_reg*8);
  3244.         assemble_long(regs.regs + dstea->reg);
  3245.     }
  3246.     } else if (dstea->data_reg >= 0) {
  3247.     compile_force_byteorder(map, dstea->data_reg, BO_NORMAL, 0);
  3248.     if (srcea->data_reg == -2) {
  3249.         assemble(0x0F); assemble(0xBA); assemble(0xC0 + dstea->data_reg + 8*(4 + code));
  3250.         assemble(srcea->data_const_off);
  3251.     } else {
  3252.         assemble(0x0F); assemble(0xA3 + 8*code);
  3253.         assemble(0xC0 + dstea->data_reg + srcea->data_reg*8);
  3254.     }
  3255.     if (optype != i_BTST)
  3256.         map->x86_dirty[dstea->data_reg] = 1;
  3257.     } else {
  3258.     int addr_code = dstea->address_reg == -2 ? 5 : dstea->address_reg + 0x80;
  3259.     compile_force_byteorder(map, dstea->address_reg, BO_NORMAL, 0);
  3260.     /* We have an address in memory */
  3261.     if (dstea->data_reg != -1)
  3262.         printf("Things don't look good in handle_bit_insns\n");
  3263.     if (srcea->data_reg == -2) {
  3264.         assemble(0x0F); assemble(0xBA);
  3265.         assemble(addr_code + 8*(4 + code));
  3266.         assemble_long(address_space + dstea->addr_const_off);
  3267.         assemble(srcea->data_const_off);
  3268.     } else {
  3269.         assemble(0x0F); assemble(0xA3 + 8*code);
  3270.         assemble(addr_code + srcea->data_reg*8);
  3271.         assemble_long(address_space + dstea->addr_const_off);
  3272.     }
  3273.  
  3274.     }
  3275.     cc_status = CC_Z_FROM_86C;
  3276. }
  3277.  
  3278. static int do_rotshi = 1;
  3279.  
  3280. static void handle_rotshi(struct register_mapping *map, int iip,
  3281.               uae_u8 *realpc, uaecptr current_addr, struct pid_undo *pud)
  3282. {
  3283.     struct ea_info eai;
  3284.     int amode_reg = insn_info[iip].dp->sreg;
  3285.     int amode_mode = insn_info[iip].dp->smode;
  3286.     wordsizes size = insn_info[iip].dp->size;
  3287.     int shiftcount;
  3288.     int mnemo = insn_info[iip].dp->mnemo;
  3289.     int shiftcode;
  3290.     int locked_eax_for_sahf = 0;
  3291.  
  3292.     switch(mnemo) {
  3293.      case i_ASLW: shiftcount = 1; mnemo = i_ASL; break;
  3294.      case i_ASRW: shiftcount = 1; mnemo = i_ASR; break;
  3295.      case i_LSLW: shiftcount = 1; mnemo = i_LSL; break;
  3296.      case i_LSRW: shiftcount = 1; mnemo = i_LSR; break;
  3297.      case i_ROLW: shiftcount = 1; mnemo = i_ROL; break;
  3298.      case i_RORW: shiftcount = 1; mnemo = i_ROR; break;
  3299.      case i_ROXLW:shiftcount = 1; mnemo = i_ROXL;break;
  3300.      case i_ROXRW:shiftcount = 1; mnemo = i_ROXR;break;
  3301.      default:
  3302.     amode_reg = insn_info[iip].dp->dreg;
  3303.     amode_mode = insn_info[iip].dp->dmode;
  3304.     shiftcount = insn_info[iip].dp->sreg;
  3305.     break;
  3306.     }
  3307.     if ((insn_info[iip].flags_live_at_end & CC68K_V) != 0) {
  3308.     if (mnemo == i_ASL) {
  3309.         generate_exit(map, insn_info[iip].address);
  3310.         printf("Can't handle this shift\n");
  3311.         return;
  3312.     } else if (mnemo == i_ASR || mnemo == i_LSR || mnemo == i_LSL) {
  3313.         remove_x86r_from_cache(map, r_EAX, 1);
  3314.         locked_eax_for_sahf = 1;
  3315.         lock_reg(map, r_EAX, 2);
  3316.     }
  3317.  
  3318.     }
  3319.     if (mnemo == i_ROXR || mnemo == i_ROXL) {
  3320.     remove_x86r_from_cache(map, r_EAX, 1);
  3321.     lock_reg(map, r_EAX, 2);
  3322.     compile_move_reg_from_mem_regoffs(r_AH, -2, 4 + (uae_u32)®flags, sz_byte);
  3323.     }
  3324.     compile_prepare_undo(map, amode_mode, amode_reg, pud);
  3325.     compile_prepareea(map, amode_mode, amode_reg, size,
  3326.               &realpc, current_addr,
  3327.               &eai, 0, EA_LOAD|EA_STORE|EA_MODIFY, 1);
  3328.  
  3329.     generate_possible_exit(map, &eai, iip, pud);
  3330.  
  3331.     compile_fetchea(map, &eai, 0, 1);
  3332.     compile_force_byteorder(map, eai.data_reg, BO_NORMAL, 0);
  3333.  
  3334.     switch (mnemo) {
  3335.      case i_ASL:
  3336.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3337.     break;
  3338.      case i_LSL:
  3339.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3340.     break;
  3341.      case i_LSR:
  3342.     shiftcode = 5; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3343.     break;
  3344.      case i_ASR:
  3345.     shiftcode = 7; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3346.     break;
  3347.      case i_ROR:
  3348.     shiftcode = 1; cc_status = CC_AFTER_RO;
  3349.     break;
  3350.      case i_ROL:
  3351.     shiftcode = 0; cc_status = CC_AFTER_RO;
  3352.     break;
  3353.      case i_ROXL:
  3354.     shiftcode = 2; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
  3355.     break;
  3356.      case i_ROXR:
  3357.     shiftcode = 3; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
  3358.     break;
  3359.     }
  3360.  
  3361.     if (size == sz_word)
  3362.     assemble(0x66);
  3363.     assemble((shiftcount == 1 ? 0xD0 : 0xC0) + (size == sz_byte ? 0 : 1));
  3364.     assemble(shiftcode*8+0xC0 + eai.data_reg);
  3365.     if (shiftcount != 1) assemble(shiftcount);
  3366.     cc_offset = 0; cc_size = size; cc_reg = eai.data_reg;
  3367.  
  3368.     if (locked_eax_for_sahf) {
  3369.     /* The trick here is that the overflow flag isn't put into AH in SAHF */
  3370.     assemble(0x9E);
  3371.     assemble(0x0B); assemble(9*1 + 0xC0);
  3372.     assemble(0x9F);
  3373.     compile_unlock_reg(map, r_EAX);
  3374.     }
  3375.     compile_note_modify(map, &eai, 0);
  3376. }
  3377.  
  3378. static void handle_rotshi_variable(struct register_mapping *map, int iip,
  3379.                    uae_u8 *realpc, uaecptr current_addr,
  3380.                    struct pid_undo *pud)
  3381. {
  3382.     struct ea_info eais, eaid;
  3383.     int mnemo = insn_info[iip].dp->mnemo;
  3384.     int shiftcode;
  3385.     char *tmp1, *tmp2;
  3386.     int locked_eax_for_sahf = 0;
  3387.  
  3388.     remove_x86r_from_cache(map, r_ECX, 1);
  3389.     lock_reg(map, r_ECX, 2);
  3390.  
  3391.     if ((insn_info[iip].flags_live_at_end & CC68K_V) != 0) {
  3392.     if (mnemo == i_ASL) {
  3393.         generate_exit(map, insn_info[iip].address);
  3394.         printf("Can't handle this shift (var)\n");
  3395.         return;
  3396.     } else if (mnemo == i_ASR || mnemo == i_LSR || mnemo == i_LSL) {
  3397.         remove_x86r_from_cache(map, r_EAX, 1);
  3398.         locked_eax_for_sahf = 1;
  3399.         lock_reg(map, r_EAX, 2);
  3400.     }
  3401.  
  3402.     }
  3403.     if (mnemo == i_ROXR || mnemo == i_ROXL) {
  3404.     remove_x86r_from_cache(map, r_EAX, 1);
  3405.     lock_reg(map, r_EAX, 2);
  3406.     compile_move_reg_from_mem_regoffs(r_AH, -2, 4 + (uae_u32)®flags,
  3407.                       sz_byte);
  3408.     }
  3409.     /* Both src and dest are Dreg modes */
  3410.     compile_prepareea(map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg,
  3411.               sz_long, &realpc, current_addr,
  3412.               &eais, 0, EA_LOAD, 1);
  3413.     compile_prepareea(map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg,
  3414.               insn_info[iip].dp->size, &realpc, current_addr,
  3415.               &eaid, 0, EA_LOAD|EA_STORE|EA_MODIFY, 1);
  3416.  
  3417.     compile_fetchea(map, &eais, 0, 1);
  3418.     compile_fetchea(map, &eaid, 1, 1);
  3419.     compile_force_byteorder(map, eais.data_reg, BO_NORMAL, 0);
  3420.     compile_force_byteorder(map, eaid.data_reg, BO_NORMAL, 0);
  3421.     compile_move_reg_reg(r_ECX, eais.data_reg, sz_long);
  3422.     /* Test against zero, and test bit 6. If 1 <= count <= 31, we can do the
  3423.      * operation, otherwise, we have to exit */
  3424.     assemble(0xF6); assemble(0xC0 + r_ECX); assemble(0x1F);
  3425.     assemble(0x74); assemble(9);
  3426.     assemble(0xF6); assemble(0xC0 + r_ECX); assemble(0x20);
  3427.  
  3428.     assemble(0x0F); assemble(0x85); tmp1 = compile_here(); assemble_ulong(0);
  3429.     generate_exit(map, insn_info[iip].address);
  3430.     tmp2 = compile_here(); compile_org (tmp1); assemble_ulong((tmp2-tmp1) + 4); compile_org(tmp2);
  3431.  
  3432.     switch (mnemo) {
  3433.      case i_ASL:
  3434.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3435.     break;
  3436.      case i_LSL:
  3437.     shiftcode = 4; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3438.     break;
  3439.      case i_LSR:
  3440.     shiftcode = 5; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3441.     break;
  3442.      case i_ASR:
  3443.     shiftcode = 7; cc_status = CC_C_FROM_86C | CC_Z_FROM_86Z | CC_N_FROM_86N | CC_V_FROM_86V | CC_X_FROM_86C;
  3444.     break;
  3445.      case i_ROR:
  3446.     shiftcode = 1; cc_status = CC_AFTER_RO;
  3447.     break;
  3448.      case i_ROL:
  3449.     shiftcode = 0; cc_status = CC_AFTER_RO;
  3450.     break;
  3451.      case i_ROXL:
  3452.     shiftcode = 2; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
  3453.     break;
  3454.      case i_ROXR:
  3455.     shiftcode = 3; assemble(0x9E); /* SAHF */ cc_status = CC_AFTER_ROX; compile_unlock_reg(map, r_EAX);
  3456.     break;
  3457.     }
  3458.  
  3459.     if (insn_info[iip].dp->size == sz_word)
  3460.     assemble(0x66);
  3461.     assemble(0xD2 + (insn_info[iip].dp->size == sz_byte ? 0 : 1));
  3462.     assemble(shiftcode*8+0xC0 + eaid.data_reg);
  3463.     cc_offset = 0; cc_size = insn_info[iip].dp->size; cc_reg = eaid.data_reg;
  3464.  
  3465.     if (locked_eax_for_sahf) {
  3466.     /* The trick here is that the overflow flag isn't put into AH in SAHF */
  3467.     assemble(0x9E);
  3468.     assemble(0x0B); assemble(9*1 + 0xC0);
  3469.     assemble(0x9F);
  3470.     compile_unlock_reg(map, r_EAX);
  3471.     }
  3472.     compile_note_modify(map, &eaid, 0);
  3473.     compile_unlock_reg(map, r_ECX);
  3474. }
  3475.  
  3476. static uae_u32 testmask = 0xF80000, testval = 0xF80000;
  3477.  
  3478. static int m68k_compile_block(struct hash_block *hb)
  3479. {
  3480.     int movem_extra = 0;
  3481.     int last_iip = m68k_scan_block(hb, &movem_extra);
  3482.     struct register_mapping map;
  3483.     int i, iip, szflag;
  3484.     uae_u8 *realpc_start = NULL;
  3485.     struct bb_info *current_bb;
  3486.     int cc_status_for_bcc = CC_SAHF;
  3487.     struct insn_reg_needs reg_needs_init;
  3488.  
  3489.     cesp = 0;
  3490.  
  3491.     if (n_compiled > n_max_comp)
  3492.     return 1;
  3493.     else if (n_compiled++ == n_max_comp)
  3494.     printf("X\n");
  3495.  
  3496.     cc_status = 0; compile_failure = 0;
  3497.  
  3498.     /* Kickstart ROM address? */
  3499.     if ((hb->he_first->addr & 0xF80000) != 0xF80000
  3500.     && 0 && !patched_syscalls)
  3501.     return 1;
  3502.  
  3503.     exits_necessary = ((hb->he_first->addr & 0xF80000) == 0xF80000 || !USER_PROGRAMS_BEHAVE);
  3504.  
  3505.     if (alloc_code (hb, last_iip + movem_extra) == NULL) {
  3506.     hb->allocfailed = 1;
  3507.     return 0;
  3508.     }
  3509.     compile_org(hb->compile_start);
  3510.     compile_last_addr = (char *)hb->compile_start + hb->alloclen;
  3511.  
  3512.     /* m68k_scan_block() will leave this all set up */
  3513.     current_bb = bb_stack;
  3514.  
  3515.     for (i = 0; i < 8; i++) {
  3516.     map.dreg_map[i] = map.areg_map[i] = -1;
  3517.     map.x86_dirty[i] = 0;
  3518.     map.x86_cache_reg[i] = -1;
  3519.     map.x86_cr_type[i] = 0;
  3520.     map.x86_const_offset[i] = 0;
  3521.     map.x86_verified[i] = 0;
  3522.     map.x86_byteorder[i] = BO_NORMAL;
  3523.     }
  3524.  
  3525.     reg_needs_init.checkpoint_no = 0;
  3526.     for (i = 0; i < 8; i++) {
  3527.     reg_needs_init.dreg_needed[i] = reg_needs_init.areg_needed[i] = -1;
  3528.     reg_needs_init.dreg_mask[i] = reg_needs_init.areg_mask[i] = ALL_X86_REGS;
  3529.     }
  3530.  
  3531.     for (iip = 0; iip < last_iip && !compile_failure; iip++) {
  3532.     uae_u8 *realpc;
  3533.     struct ea_info eainfo[8];
  3534.     uaecptr current_addr;
  3535.     struct pid_undo pub;
  3536.     struct insn_reg_needs this_reg_needs = reg_needs_init;
  3537.  
  3538.     /* Set up locks for a new insn. We don't bother to clear this
  3539.      * properly after compiling one insn. */
  3540.     for (i = 0; i < 8; i++) {
  3541.         map.x86_users[i] = i == r_ESP ? 1 : 0;
  3542.         map.x86_locked[i] = i == r_ESP ? 2 : 0;
  3543.     }
  3544.  
  3545.     pub.used = 0;
  3546.     current_addr = insn_info[iip].address + 2;
  3547.  
  3548.     if (iip == current_bb->first_iip) {
  3549.         sync_reg_cache(&map, 1);
  3550.         if (!quiet_compile)
  3551.         printf("Compiling %08lx\n", current_bb->h->addr);
  3552.  
  3553.         realpc_start = get_real_address(current_bb->h->addr);
  3554.         current_bb->h->execute = (code_execfunc)compile_here();
  3555.         current_bb->h->matchword = *(uae_u32 *)realpc_start;
  3556.         cc_status_for_bcc = CC_SAHF;
  3557.     }
  3558.  
  3559.     realpc = realpc_start + (current_addr - current_bb->h->addr);
  3560.  
  3561.     insn_info[iip].compiled_jumpaddr = compile_here();
  3562.     insn_info[iip].compiled_fillin = NULL;
  3563.  
  3564.     if (insn_info[iip].jump_target) {
  3565.         if (cesp == CE_STACK_SIZE) {
  3566.         generate_exit(NULL, insn_info[iip].address);
  3567.         compile_failure = 1;
  3568.         } else {
  3569.         assemble(0xFE); assemble(0x05 + 8*1); assemble_long(&nr_bbs_to_run);
  3570.         assemble(0x0F); assemble(0x84); /* JE finish */
  3571.         compile_exit_stack[cesp].noflush = 1;
  3572.         compile_exit_stack[cesp].address = current_bb->h;
  3573.         compile_exit_stack[cesp].jmpoffs = compile_here();
  3574.         assemble_ulong(0);
  3575.         cesp++;
  3576.         }
  3577.     }
  3578.     /*
  3579.      * This will sort out all insns we can't compile, including
  3580.      * jumps out of this block */
  3581.     if (insn_info[iip].stop_translation == 1) {
  3582.         generate_exit(&map, insn_info[iip].address);
  3583.         cc_status = 0;
  3584.     } else switch (insn_info[iip].dp->mnemo) {
  3585.      case i_NOP:
  3586.         cc_status = 0;
  3587.         if (!quiet_compile)
  3588.         printf("Compiling a NOP\n");
  3589.         break;
  3590.  
  3591.      case i_RTS:
  3592.         sync_reg_cache(&map, 1);
  3593.         lock_reg(&map, r_ECX, 2);
  3594.         lock_reg(&map, r_EBX, 2);
  3595.         {
  3596.         char *tmp1, *tmp2, *tmp3;
  3597.  
  3598.         /* fetch (A7) */
  3599.         assemble(0x8B); assemble(0x5 + r_EBX*8); assemble_long(regs.regs + 15);
  3600.         assemble(0x8B); assemble(0x80 + 9*r_EBX); assemble_long(address_space);
  3601.         assemble(0x0F); /* bswapl x86r */
  3602.         assemble(0xC8 + r_EBX);
  3603.         /* fetch jsr_num */
  3604.         assemble(0x8B); assemble(0x5 + r_ECX*8); assemble_long(&jsr_num);
  3605.         assemble(0x09); assemble(0xC0 + 9*r_ECX);
  3606.         assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
  3607.         assemble(0xFF); assemble(1*8 + 0xC0 + r_ECX);
  3608.         /* cmpl %ebx,disp32(,%ecx,4) */
  3609.         assemble(0x39); assemble(0x04 + 8*r_EBX); assemble(0x8d);
  3610.         assemble_long(jsr_rets);
  3611.         assemble(0x0F); assemble(0x85); tmp2 = compile_here(); assemble_ulong(0);
  3612.         /* movl disp32(,%ecx,4),%ebx */
  3613.         assemble(0x8B); assemble(0x04 + 8*r_EBX); assemble(0x8d);
  3614.         assemble_long(jsr_hash);
  3615.         /* movl execute(%ebx), %ebx */
  3616.         assemble(0x8B); assemble(0x040 + 9*r_EBX); assemble((int)&((struct hash_entry *)0)->execute);
  3617.         assemble(0x09); assemble(0xC0 + 9*r_EBX);
  3618.         assemble(0x0F); assemble(0x85); tmp3 = compile_here(); assemble_ulong(0);
  3619.         compile_org(tmp1); assemble_ulong(tmp3 - tmp1);
  3620.         compile_org(tmp2); assemble_ulong(tmp3 - tmp2);
  3621.         compile_org(tmp3 + 4);
  3622.         generate_exit(&map, insn_info[iip].address);
  3623.         tmp1 = compile_here();
  3624.         compile_org(tmp3); assemble_ulong((tmp1-tmp3)-4);
  3625.         compile_org(tmp1);
  3626.         assemble(0x89); assemble(0x5 + r_ECX*8); assemble_long(&jsr_num);
  3627.         assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(-4);
  3628.         /* Off we go */
  3629.         assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
  3630.         }
  3631.         break;
  3632.  
  3633.      case i_JMP:
  3634.         sync_reg_cache(&map, 1);
  3635.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3636.                   insn_info[iip].dp->sreg,
  3637.                   insn_info[iip].dp->size, &realpc, current_addr,
  3638.                   eainfo, 0, EA_LOAD, 1);
  3639.         {
  3640.         char *tmp1, *tmp2, *tmp3;
  3641.  
  3642.         struct hash_entry *tmph;
  3643.         if (eainfo[0].address_reg != -2 || (tmph = get_hash_for_func(eainfo[0].addr_const_off, 1)) == 0) {
  3644.             if (eainfo[0].address_reg != -2 && !quiet_compile)
  3645.             printf("Can't compile indirect JMP\n");
  3646.             generate_exit(&map, insn_info[iip].address);
  3647.             break;
  3648.         }
  3649.         /* check whether the destination has compiled code */
  3650.         assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
  3651.         assemble(0x09); assemble(0xC0 + 9*r_EBX);
  3652.         assemble(0x0F); assemble(0x85); tmp1 = compile_here(); assemble_ulong(0);
  3653.         generate_exit(&map, insn_info[iip].address);
  3654.         tmp2 = compile_here(); compile_org(tmp1);
  3655.         assemble_ulong((tmp2 - tmp1) - 4);
  3656.         compile_org(tmp2);
  3657.         /* Off we go */
  3658.         assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
  3659.         }
  3660.         cc_status = 0;
  3661.         break;
  3662.  
  3663.      case i_JSR:
  3664.         sync_reg_cache(&map, 1);
  3665.         lock_reg(&map, r_ECX, 2);
  3666.         lock_reg(&map, r_EBX, 2);
  3667.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3668.                   insn_info[iip].dp->sreg,
  3669.                   insn_info[iip].dp->size, &realpc, current_addr,
  3670.                   eainfo, 0, EA_LOAD, 1);
  3671.         {
  3672.         char *tmp1, *tmp2, *tmp3;
  3673.  
  3674.         struct hash_entry *tmph;
  3675.         if (eainfo[0].address_reg != -2 || (tmph = get_hash_for_func(eainfo[0].addr_const_off, 1)) == 0) {
  3676.             if (eainfo[0].address_reg != -2 && !quiet_compile)
  3677.             printf("Can't compile indirect JSR\n");
  3678.             generate_exit(&map, insn_info[iip].address);
  3679.             break;
  3680.         }
  3681.         assert(iip + 1 < last_iip);
  3682.         assert(iip == current_bb->last_iip);
  3683.         /* check whether the destination has compiled code */
  3684.         assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
  3685.         assemble(0x09); assemble(0xC0 + 9*r_EBX);
  3686.         assemble(0x0F); assemble(0x84); tmp3 = compile_here(); assemble_ulong(0);
  3687.         /* check for stack overflow */
  3688.         assemble(0x8B); assemble(r_ECX*8 + 0x05); assemble_long(&jsr_num);
  3689.         assemble(0xF7); assemble(0xC0+r_ECX); assemble_ulong(MAX_JSRS);
  3690.         assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
  3691.         generate_exit(&map, insn_info[iip].address);
  3692.         tmp2 = compile_here(); compile_org(tmp1); assemble_ulong((tmp2 - tmp1) - 4);
  3693.         compile_org(tmp3); assemble_ulong(tmp1-tmp3);
  3694.         compile_org(tmp2);
  3695.         /* movl $something,disp32(,%ecx,4) */
  3696.         assemble(0xC7); assemble(0x04); assemble(0x8d);
  3697.         assemble_long(jsr_rets); assemble_ulong(insn_info[iip+1].address);
  3698.         assemble(0xC7); assemble(0x04); assemble(0x8d);
  3699.         assemble_long(jsr_hash); assemble_long((current_bb + 1)->h);
  3700.         /* incl jsr_num */
  3701.         assemble(0xFF); assemble(0x05); assemble_long(&jsr_num);
  3702.         /* Put things on the 68k stack */
  3703.         assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(4);
  3704.         assemble(0x8B); assemble(r_ECX*8+ 0x05); assemble_long(regs.regs + 15);
  3705.         assemble(0xC7); assemble(0x80 + r_ECX); assemble_long(address_space);
  3706.         assemble_ulong_68k(insn_info[iip+1].address);
  3707.         /* Off we go */
  3708.         assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
  3709.         }
  3710.         break;
  3711.  
  3712.      case i_BSR:
  3713.         sync_reg_cache(&map, 1);
  3714.         lock_reg(&map, r_ECX, 2);
  3715.         lock_reg(&map, r_EBX, 2);
  3716.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3717.                   insn_info[iip].dp->sreg,
  3718.                   insn_info[iip].dp->size, &realpc, current_addr,
  3719.                   eainfo, 0, EA_LOAD, 1);
  3720.         {
  3721.         char *tmp1, *tmp2, *tmp3;
  3722.         uaecptr dest = insn_info[iip].address + 2 + (uae_s32)eainfo[0].data_const_off;
  3723.         struct hash_entry *tmph;
  3724.         if ((tmph = get_hash_for_func(dest, 1)) == 0) {
  3725.             generate_exit(&map, insn_info[iip].address);
  3726.             break;
  3727.         }
  3728.         assert(iip + 1 < last_iip);
  3729.         assert(iip == current_bb->last_iip);
  3730.  
  3731.         /* check whether the destination has compiled code */
  3732.         assemble(0x8B); assemble(r_EBX*8 + 0x05); assemble_long(&(tmph->execute));
  3733.         assemble(0x09); assemble(0xC0 + 9*r_EBX);
  3734.         assemble(0x0F); assemble(0x84); tmp3 = compile_here(); assemble_ulong(0);
  3735.         /* check for stack overflow */
  3736.         assemble(0x8B); assemble(r_ECX*8 + 0x05); assemble_long(&jsr_num);
  3737.         assemble(0xF7); assemble(0xC0+r_ECX); assemble_ulong(MAX_JSRS);
  3738.         assemble(0x0F); assemble(0x84); tmp1 = compile_here(); assemble_ulong(0);
  3739.         generate_exit(&map, insn_info[iip].address);
  3740.         tmp2 = compile_here(); compile_org(tmp1); assemble_ulong((tmp2 - tmp1) - 4);
  3741.         compile_org(tmp3); assemble_ulong(tmp1-tmp3);
  3742.         compile_org(tmp2);
  3743.         /* movl $something,disp32(,%ecx,4) */
  3744.         assemble(0xC7); assemble(0x04); assemble(0x8d);
  3745.         assemble_long(jsr_rets); assemble_ulong(insn_info[iip+1].address);
  3746.         assemble(0xC7); assemble(0x04); assemble(0x8d);
  3747.         assemble_long(jsr_hash); assemble_long((current_bb + 1)->h);
  3748.         /* incl jsr_num */
  3749.         assemble(0xFF); assemble(0x05); assemble_long(&jsr_num);
  3750.         /* Put things on the 68k stack */
  3751.         assemble(0x83); assemble(0x05 + 5*8); assemble_long(regs.regs + 15); assemble(4);
  3752.         assemble(0x8B); assemble(r_ECX*8+ 0x05); assemble_long(regs.regs + 15);
  3753.         assemble(0xC7); assemble(0x80 + r_ECX); assemble_long(address_space);
  3754.         assemble_ulong_68k(insn_info[iip+1].address);
  3755.         /* Off we go */
  3756.         assemble(0xFF); assemble(4*8 + 0xC0 + r_EBX);
  3757.         }
  3758.         break;
  3759.  
  3760.      case i_Bcc:
  3761.         sync_reg_cache(&map, 0);
  3762.         compile_handle_bcc(&map, iip, cc_status_for_bcc);
  3763.         cc_status = 0;
  3764.         break;
  3765.  
  3766.      case i_DBcc:
  3767.         sync_reg_cache(&map, 0);
  3768.         remove_x86r_from_cache(&map, map.dreg_map[insn_info[iip].dp->sreg], 1);
  3769.         compile_handle_dbcc(&map, iip, cc_status_for_bcc,
  3770.                 insn_info[iip].dp->sreg);
  3771.         cc_status = 0;
  3772.         break;
  3773. #if 0
  3774.      case i_Scc:
  3775.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3776.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3777.                   insn_info[iip].dp->sreg,
  3778.                   insn_info[iip].dp->size, &realpc, current_addr,
  3779.                   eainfo, 0, EA_STORE, 1);
  3780.  
  3781.         generate_possible_exit(&map, eainfo, iip, &pub);
  3782.         srcreg2 = get_;
  3783.         compile_note_modify(&map, eainfo, 0);
  3784.  
  3785.         cc_status = 0;
  3786.         break;
  3787. #endif
  3788.      case i_ADD:
  3789.      case i_SUB:
  3790.      case i_CMP:
  3791.      case i_CMPM:
  3792.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3793.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3794.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3795.                   insn_info[iip].dp->sreg,
  3796.                   insn_info[iip].dp->size, &realpc, current_addr,
  3797.                   eainfo, 0, EA_LOAD, 1);
  3798.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3799.                   insn_info[iip].dp->dreg,
  3800.                   insn_info[iip].dp->size, &realpc, current_addr,
  3801.                   eainfo, 1,
  3802.                   (insn_info[iip].dp->mnemo == i_ADD || insn_info[iip].dp->mnemo == i_SUB
  3803.                    ? EA_MODIFY | EA_LOAD | EA_STORE
  3804.                    : EA_LOAD | EA_STORE), 1);
  3805.  
  3806.         generate_possible_exit(&map, eainfo, iip, &pub);
  3807.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3808.  
  3809.         compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
  3810.  
  3811.         switch (insn_info[iip].dp->mnemo) {
  3812.          case i_ADD: compile_eas(&map, eainfo, 0, 1, 0); break;
  3813.          case i_SUB: compile_eas(&map, eainfo, 0, 1, 5); break;
  3814.          case i_CMP: case i_CMPM: compile_eas(&map, eainfo, 0, 1, 7); break;
  3815.         }
  3816.  
  3817.         if (insn_info[iip].dp->mnemo != i_CMP && insn_info[iip].dp->mnemo != i_CMPM)
  3818.         compile_note_modify(&map, eainfo, 1);
  3819.         switch (insn_info[iip].dp->mnemo) {
  3820.          case i_ADD:
  3821.          case i_SUB:
  3822.         cc_status = CC_X_FROM_86C | CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
  3823.         break;
  3824.          case i_CMP:
  3825.          case i_CMPM:
  3826.         cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
  3827.         break;
  3828.         }
  3829.         break;
  3830.  
  3831.      case i_ADDX:
  3832.      case i_SUBX:
  3833.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3834.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3835.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3836.                   insn_info[iip].dp->sreg,
  3837.                   insn_info[iip].dp->size, &realpc, current_addr,
  3838.                   eainfo, 0, EA_LOAD, 1);
  3839.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3840.                   insn_info[iip].dp->dreg,
  3841.                   insn_info[iip].dp->size, &realpc, current_addr,
  3842.                   eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
  3843.  
  3844.         generate_possible_exit(&map, eainfo, iip, &pub);
  3845.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3846.  
  3847.         compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
  3848.  
  3849.         /* bt $0, regflags+4 ; get carry */
  3850.         assemble(0x0F); assemble(0xBA); assemble(0x5+4*8);
  3851.         assemble_ulong(4 + (uae_u32)®flags); assemble(0);
  3852.  
  3853.         switch (insn_info[iip].dp->mnemo) {
  3854.          case i_ADDX: compile_eas(&map, eainfo, 0, 1, 2); break;
  3855.          case i_SUBX: compile_eas(&map, eainfo, 0, 1, 3); break;
  3856.         }
  3857.         compile_note_modify(&map, eainfo, 1);
  3858.  
  3859.         if (insn_info[iip].flags_live_at_end & CC68K_Z) {
  3860.         /* Darn. */
  3861.         int tmpr = get_free_x86_register(&map, ALL_X86_REGS);
  3862.         /* pushfl; popl tmpr */
  3863.         assemble(0x9C); assemble(0x58+tmpr);
  3864.         /* Magic! */
  3865.         /* andl tmpr, regflags; andl $~0x40,tmpr; orl tmpr, regflags */
  3866.         assemble(0x21); assemble(0x05 + 8*tmpr); assemble_long(®flags);
  3867.         assemble(0x81); assemble(0xC0 + 8*4 + tmpr); assemble_ulong(~0x40);
  3868.         assemble(0x09); assemble(0x05 + 8*tmpr); assemble_long(®flags);
  3869.         compile_move_reg_to_mem_regoffs(-2, 4 + (uae_u32)®flags, tmpr, sz_long);
  3870.         cc_status = 0;
  3871.         } else {
  3872.         /* Lies! */
  3873.         cc_status = CC_X_FROM_86C | CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  3874.         }
  3875.         break;
  3876.  
  3877.      case i_MULU:
  3878.      case i_MULS:
  3879.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3880.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3881.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3882.                   insn_info[iip].dp->sreg,
  3883.                   insn_info[iip].dp->size, &realpc, current_addr,
  3884.                   eainfo, 0, EA_LOAD, 1);
  3885.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3886.                   insn_info[iip].dp->dreg,
  3887.                   insn_info[iip].dp->size, &realpc, current_addr,
  3888.                   eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
  3889.  
  3890.         generate_possible_exit(&map, eainfo, iip, &pub);
  3891.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  3892.  
  3893.         compile_loadeas(&map, eainfo, 0, 1, regonly_alternatives, 0, 1);
  3894.  
  3895.         /* Extend the regs properly */
  3896.         remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
  3897.         switch (insn_info[iip].dp->mnemo) {
  3898.          case i_MULU:
  3899.         assemble(0x81); assemble(0xC0+4*8 + eainfo[0].data_reg); assemble_ulong(0xFFFF);
  3900.         assemble(0x81); assemble(0xC0+4*8 + eainfo[1].data_reg); assemble_ulong(0xFFFF);
  3901.         break;
  3902.          case i_MULS:
  3903.         assemble(0x0F); assemble(0xBF); assemble(0xC0 + 9*eainfo[0].data_reg);
  3904.         assemble(0x0F); assemble(0xBF); assemble(0xC0 + 9*eainfo[1].data_reg);
  3905.         break;
  3906.         }
  3907.         /* and multiply */
  3908.         assemble(0x0F); assemble(0xAF); assemble(0xC0 + 8*eainfo[1].data_reg + eainfo[0].data_reg);
  3909.         compile_note_modify(&map, eainfo, 1);
  3910.         cc_status = CC_TEST_REG;
  3911.         cc_reg = eainfo[1].data_reg;
  3912.         cc_offset = 0;
  3913.         cc_size = sz_long;
  3914.         break;
  3915.  
  3916.      case i_ADDA:
  3917.      case i_SUBA:
  3918.      case i_CMPA:
  3919.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3920.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3921.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3922.                   insn_info[iip].dp->sreg,
  3923.                   insn_info[iip].dp->size, &realpc, current_addr,
  3924.                   eainfo, 0, EA_LOAD, 1);
  3925.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3926.                   insn_info[iip].dp->dreg,
  3927.                   sz_long, &realpc, current_addr,
  3928.                   eainfo, 1,
  3929.                   (insn_info[iip].dp->mnemo == i_ADDA || insn_info[iip].dp->mnemo == i_SUBA
  3930.                    ? EA_MODIFY | EA_LOAD | EA_STORE
  3931.                    : EA_LOAD | EA_STORE),
  3932.                   1);
  3933.  
  3934.         generate_possible_exit(&map, eainfo, iip, &pub);
  3935.  
  3936.         compile_loadeas(&map, eainfo, 0, 1,
  3937.                 insn_info[iip].dp->size == sz_word ? binop_worda_alternatives : binop_alternatives,
  3938.                 0, 1);
  3939.  
  3940.         if (insn_info[iip].dp->size == sz_word) {
  3941.         remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
  3942.         compile_extend_long(&map, eainfo[0].data_reg, sz_word);
  3943.         }
  3944.         eainfo[0].size = sz_long;
  3945.  
  3946.         switch (insn_info[iip].dp->mnemo) {
  3947.          case i_ADDA: compile_eas(&map, eainfo, 0, 1, 0); break;
  3948.          case i_SUBA: compile_eas(&map, eainfo, 0, 1, 5); break;
  3949.          case i_CMPA: compile_eas(&map, eainfo, 0, 1, 7); break;
  3950.         }
  3951.  
  3952.         if (insn_info[iip].dp->mnemo == i_CMPA) {
  3953.         cc_status = CC_Z_FROM_86Z |CC_C_FROM_86C |CC_V_FROM_86V |CC_N_FROM_86N;
  3954.         } else {
  3955.         compile_note_modify(&map, eainfo, 1);
  3956.         cc_status = 0;
  3957.         }
  3958.         break;
  3959.  
  3960.      case i_MOVE:
  3961.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3962.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  3963.         compile_prepareea(&map, insn_info[iip].dp->smode,
  3964.                   insn_info[iip].dp->sreg,
  3965.                   insn_info[iip].dp->size, &realpc, current_addr,
  3966.                   eainfo, 0, EA_LOAD, 1);
  3967.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  3968.                   insn_info[iip].dp->dreg,
  3969.                   insn_info[iip].dp->size, &realpc, current_addr,
  3970.                   eainfo, 1, EA_STORE, 1);
  3971.  
  3972.         generate_possible_exit(&map, eainfo, iip, &pub);
  3973.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  3974.  
  3975.         compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 1, 0);
  3976.         compile_storeea(&map, eainfo, 0, 1);
  3977.  
  3978.         if (eainfo[0].data_reg == -2) {
  3979.         cc_status = CC_TEST_REG;
  3980.         cc_reg = -2;
  3981.         cc_offset = eainfo[0].data_const_off;
  3982.         } else if (eainfo[0].data_reg == -1) {
  3983.         if (eainfo[1].data_reg == -1)
  3984.             printf("Don't know where to get flags from\n");
  3985.         cc_status = CC_TEST_REG;
  3986.         cc_offset = 0;
  3987.         cc_reg = eainfo[1].data_reg;
  3988.         } else {
  3989.         cc_status = CC_TEST_REG;
  3990.         cc_reg = eainfo[0].data_reg;
  3991.         cc_offset = 0;
  3992.         }
  3993.         cc_size = eainfo[0].size;
  3994.  
  3995.         break;
  3996.  
  3997.      case i_MOVEA:
  3998.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  3999.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4000.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4001.                   insn_info[iip].dp->sreg,
  4002.                   insn_info[iip].dp->size, &realpc, current_addr,
  4003.                   eainfo, 0, EA_LOAD, 1);
  4004.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4005.                   insn_info[iip].dp->dreg,
  4006.                   sz_long, &realpc, current_addr,
  4007.                   eainfo, 1, EA_STORE, 1);
  4008.  
  4009.         generate_possible_exit(&map, eainfo, iip, &pub);
  4010.  
  4011.         compile_loadeas(&map, eainfo, 0, 1,
  4012.                 insn_info[iip].dp->size == sz_word ? binop_worda_alternatives : binop_alternatives,
  4013.                 0, 0);
  4014.  
  4015.         if (insn_info[iip].dp->size == sz_word) {
  4016.         remove_x86r_from_cache(&map, eainfo[0].data_reg, 0);
  4017.         compile_extend_long(&map, eainfo[0].data_reg, sz_word);
  4018.         }
  4019.         eainfo[0].size = sz_long;
  4020.  
  4021.         compile_storeea(&map, eainfo, 0, 1);
  4022.  
  4023.         cc_status = 0;
  4024.         break;
  4025.  
  4026.      case i_EXG:
  4027.         if (insn_info[iip].dp->smode != insn_info[iip].dp->dmode
  4028.         || insn_info[iip].dp->sreg != insn_info[iip].dp->dreg)
  4029.         {
  4030.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4031.                   insn_info[iip].dp->sreg,
  4032.                   sz_long, &realpc, current_addr,
  4033.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4034.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4035.                   insn_info[iip].dp->dreg,
  4036.                   sz_long, &realpc, current_addr,
  4037.                   eainfo, 1, EA_LOAD|EA_STORE, 1);
  4038.  
  4039.         compile_loadeas(&map, eainfo, 0, 1, regonly_alternatives, 0, 1);
  4040.         compile_storeea(&map, eainfo, 1, 0);
  4041.         compile_storeea(&map, eainfo, 0, 1);
  4042.         }
  4043.  
  4044.         cc_status = 0;
  4045.         break;
  4046.  
  4047.      case i_LINK:
  4048.         compile_prepare_undo(&map, Apdi, 7, &pub);
  4049.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4050.                   insn_info[iip].dp->sreg,
  4051.                   sz_long, &realpc, current_addr,
  4052.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4053.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4054.                   insn_info[iip].dp->dreg,
  4055.                   sz_long, &realpc, current_addr,
  4056.                   eainfo, 1, EA_LOAD, 1);
  4057.         compile_prepareea(&map, Apdi, 7, sz_long, &realpc, current_addr,
  4058.                   eainfo, 2, EA_STORE, 1);
  4059.  
  4060.         generate_possible_exit(&map, eainfo+2, iip, &pub);
  4061.  
  4062.         compile_fetchea(&map, eainfo, 0, 1);
  4063.         /* we know this is a constant - no need to fetch it*/
  4064.         /* compile_fetchea(&map, eainfo, 1); */
  4065.         compile_storeea(&map, eainfo, 0, 2); /* An -> -(A7) */
  4066.  
  4067.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  4068.                   eainfo, 3, EA_STORE, 1);
  4069.         compile_fetchea(&map, eainfo, 3, 1);
  4070.         compile_storeea(&map, eainfo, 3, 0); /* A7 -> An */
  4071.  
  4072.         /* @@@ 020 */
  4073.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  4074.                   eainfo, 4, EA_LOAD, 1);
  4075.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  4076.                   eainfo, 5, EA_STORE, 1);
  4077.         compile_fetchea(&map, eainfo, 4, 1);
  4078.         eainfo[4].data_const_off += (uae_s16)eainfo[1].data_const_off;
  4079.         compile_storeea(&map, eainfo, 4, 5); /* A7+off -> A7 */
  4080.         cc_status = 0;
  4081.         break;
  4082.  
  4083.      case i_UNLK:
  4084.         compile_prepareea(&map, Areg,
  4085.                   insn_info[iip].dp->sreg,
  4086.                   sz_long, &realpc, current_addr,
  4087.                   eainfo, 0, EA_LOAD, 1);
  4088.         compile_prepareea(&map, Areg, 7, sz_long, &realpc, current_addr,
  4089.                   eainfo, 1, EA_STORE, 1);
  4090.  
  4091.         generate_possible_exit(&map, eainfo + 0, iip, &pub);
  4092.  
  4093.         compile_fetchea(&map, eainfo, 0, 1);
  4094.         compile_storeea(&map, eainfo, 0, 1);
  4095.  
  4096.         /* The Apdi could of course point to a non-memory area, but undos
  4097.          * are difficult here, and anyway: which program does evil hacks
  4098.          * with UNLK? */
  4099.         compile_prepareea(&map, Aipi, 7, sz_long, &realpc, current_addr,
  4100.                   eainfo, 2, EA_LOAD, 1);
  4101.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4102.                   insn_info[iip].dp->sreg,
  4103.                   sz_long, &realpc, current_addr,
  4104.                   eainfo, 3, EA_STORE, 1);
  4105.         compile_fetchea(&map, eainfo, 2, 1);
  4106.         compile_storeea(&map, eainfo, 2, 3);
  4107.  
  4108.         cc_status = 0;
  4109.         break;
  4110.  
  4111.      case i_OR:
  4112.      case i_AND:
  4113.      case i_EOR:
  4114.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4115.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4116.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4117.                   insn_info[iip].dp->sreg,
  4118.                   insn_info[iip].dp->size, &realpc, current_addr,
  4119.                   eainfo, 0, EA_LOAD, 1);
  4120.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4121.                   insn_info[iip].dp->dreg,
  4122.                   insn_info[iip].dp->size, &realpc, current_addr,
  4123.                   eainfo, 1, EA_MODIFY | EA_LOAD | EA_STORE, 1);
  4124.  
  4125.         generate_possible_exit(&map, eainfo, iip, &pub);
  4126.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  4127.  
  4128.         compile_loadeas(&map, eainfo, 0, 1, binop_alternatives, 0, 1);
  4129.  
  4130.         switch (insn_info[iip].dp->mnemo) {
  4131.          case i_AND: compile_eas(&map, eainfo, 0, 1, 4); break;
  4132.          case i_EOR: compile_eas(&map, eainfo, 0, 1, 6); break;
  4133.          case i_OR:  compile_eas(&map, eainfo, 0, 1, 1); break;
  4134.         }
  4135.  
  4136.         compile_note_modify(&map, eainfo, 1);
  4137.         cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N;
  4138.         break;
  4139.  
  4140.      case i_TST:
  4141.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4142.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4143.                   insn_info[iip].dp->sreg,
  4144.                   insn_info[iip].dp->size, &realpc, current_addr,
  4145.                   eainfo, 0, EA_LOAD, 1);
  4146.  
  4147.         generate_possible_exit(&map, eainfo, iip, &pub);
  4148.  
  4149.         compile_fetchea(&map, eainfo, 0, 1);
  4150.         cc_status = CC_TEST_REG;
  4151.         cc_reg = eainfo[0].data_reg;
  4152.         cc_offset = 0;
  4153.         cc_size = eainfo[0].size;
  4154.         break;
  4155.  
  4156.      case i_CLR:
  4157.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4158.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4159.                   insn_info[iip].dp->sreg,
  4160.                   insn_info[iip].dp->size, &realpc, current_addr,
  4161.                   eainfo, 0, EA_STORE, 1);
  4162.         compile_prepareea(&map, immi, 0, sz_long, &realpc, current_addr,
  4163.                   eainfo, 1, EA_LOAD, 1);
  4164.         generate_possible_exit(&map, eainfo + 0, iip, &pub);
  4165.         compile_loadeas(&map, eainfo, 1, 0, binop_alternatives, 1, 0);
  4166.         compile_storeea(&map, eainfo, 1, 0);
  4167.  
  4168.         cc_status = CC_TEST_REG;
  4169.         cc_reg = -2;
  4170.         cc_offset = 0;
  4171.         cc_size = eainfo[0].size;
  4172.         break;
  4173.  
  4174.      case i_EXT:
  4175.         /* No exits, no undo - this is always a Dreg; fetchea will get it in a reg
  4176.          * without offset */
  4177.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4178.                   insn_info[iip].dp->sreg,
  4179.                   insn_info[iip].dp->size == sz_long ? sz_word : sz_byte,
  4180.                   &realpc, current_addr,
  4181.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4182.         compile_fetchea(&map, eainfo, 0, 1);
  4183.         compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
  4184.  
  4185.         if (insn_info[iip].dp->size == sz_word)
  4186.         assemble(0x66);
  4187.         assemble(0x0F);
  4188.         if (insn_info[iip].dp->size == sz_long)
  4189.         assemble(0xBF);
  4190.         else
  4191.         assemble(0xBE);
  4192.  
  4193.         assemble(0xC0 + 9*eainfo[0].data_reg);
  4194.         map.x86_dirty[eainfo[0].data_reg] = 1;
  4195.  
  4196.         cc_status = CC_TEST_REG;
  4197.         cc_reg = eainfo[0].data_reg;
  4198.         cc_offset = 0;
  4199.         cc_size = eainfo[0].size;
  4200.         break;
  4201.  
  4202.      case i_NOT:
  4203.      case i_NEG:
  4204.         szflag = insn_info[iip].dp->size == sz_byte ? 0 : 1;
  4205.  
  4206.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4207.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4208.                   insn_info[iip].dp->sreg,
  4209.                   insn_info[iip].dp->size,
  4210.                   &realpc, current_addr,
  4211.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4212.  
  4213.         generate_possible_exit(&map, eainfo, iip, &pub);
  4214.  
  4215.         compile_fetchea(&map, eainfo, 0, 1);
  4216.         compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
  4217.  
  4218.         if (insn_info[iip].dp->size == sz_word)
  4219.         assemble(0x66);
  4220.         assemble(0xF6 + szflag);
  4221.  
  4222.         assemble(0xC0 + eainfo[0].data_reg + 8*(insn_info[iip].dp->mnemo == i_NOT ? 2 : 3));
  4223.         compile_note_modify(&map, eainfo, 0);
  4224.  
  4225.         if (insn_info[iip].dp->mnemo == i_NEG)
  4226.         cc_status = CC_Z_FROM_86Z | CC_C_FROM_86C | CC_V_FROM_86V | CC_N_FROM_86N | CC_X_FROM_86C;
  4227.         else {
  4228.         cc_status = CC_TEST_REG;
  4229.         cc_reg = eainfo[0].data_reg;
  4230.         cc_offset = 0;
  4231.         cc_size = eainfo[0].size;
  4232.         }
  4233.         break;
  4234.  
  4235.      case i_SWAP:
  4236.         /* No exits, no undo - this is always a Dreg; fetchea will get it in a reg
  4237.          * without offset */
  4238.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4239.                   insn_info[iip].dp->sreg, sz_long,
  4240.                   &realpc, current_addr,
  4241.                   eainfo, 0, EA_LOAD|EA_STORE, 1);
  4242.  
  4243.         compile_fetchea(&map, eainfo, 0, 1);
  4244.         compile_force_byteorder(&map, eainfo[0].data_reg, BO_NORMAL, 0);
  4245.  
  4246.         /* roll $16, srcreg */
  4247.         assemble(0xC1); assemble(0xC0 + eainfo[0].data_reg); assemble(16);
  4248.  
  4249.         /* @@@ un-shortcut */
  4250.         map.x86_dirty[eainfo[0].data_reg] = 1;
  4251.  
  4252.         cc_status = CC_TEST_REG;
  4253.         cc_reg = eainfo[0].data_reg;
  4254.         cc_offset = 0;
  4255.         cc_size = eainfo[0].size;
  4256.         break;
  4257.  
  4258.      case i_LEA:
  4259.         /* No exits necessary here: never touches memory */
  4260.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4261.                   insn_info[iip].dp->sreg,
  4262.                   insn_info[iip].dp->size, &realpc, current_addr,
  4263.                   eainfo, 0, 0, 1);
  4264.         eainfo[0].data_reg = eainfo[0].address_reg;
  4265.         eainfo[0].data_const_off = eainfo[0].addr_const_off;
  4266.         eainfo[0].address_reg = -1;
  4267.         compile_get_excl_lock(&map, eainfo + 0);
  4268.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4269.                   insn_info[iip].dp->dreg,
  4270.                   sz_long, &realpc, current_addr,
  4271.                   eainfo, 1, EA_STORE, 1);
  4272.         compile_storeea(&map, eainfo, 0, 1);
  4273.         cc_status = 0;
  4274.         break;
  4275.  
  4276.      case i_PEA:
  4277.         compile_prepare_undo(&map, Apdi, 7, &pub);
  4278.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4279.                   insn_info[iip].dp->sreg,
  4280.                   insn_info[iip].dp->size, &realpc, current_addr,
  4281.                   eainfo, 0, 0, 1);
  4282.         eainfo[0].data_reg = eainfo[0].address_reg;
  4283.         eainfo[0].data_const_off = eainfo[0].addr_const_off;
  4284.         eainfo[0].address_reg = -1;
  4285.         compile_get_excl_lock(&map, eainfo + 0);
  4286.         compile_prepareea(&map, Apdi, 7, sz_long, &realpc, current_addr,
  4287.                   eainfo, 1, EA_STORE, 1);
  4288.  
  4289.         generate_possible_exit(&map, eainfo+1, iip, &pub);
  4290.         compile_storeea(&map, eainfo, 0, 1);
  4291.  
  4292.         cc_status = 0;
  4293.         break;
  4294.  
  4295.      case i_MVMEL:
  4296.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4297.                   insn_info[iip].dp->sreg,
  4298.                   sz_word, &realpc, current_addr,
  4299.                   eainfo, 0, EA_LOAD, 1);
  4300.         sync_reg_cache(&map, 0);
  4301.         {
  4302.         /* Scratch 0 holds the registers while they are being moved
  4303.          * from/to memory. Scratch 1 points at regs.d. Scratch 2
  4304.          * points at the base addr in memory where to fetch data
  4305.          * from.
  4306.          */
  4307.         int scratch0, scratch1, scratch2;
  4308.         uae_u16 mask = eainfo[0].data_const_off;
  4309.         int bits = count_bits(mask);
  4310.         int size = insn_info[iip].dp->size == sz_long ? 4 : 2;
  4311.         int i;
  4312.         uae_u8 x86amode;
  4313.         uae_u32 current_offs = 0;
  4314.  
  4315.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4316.         /* !!! Note current_addr + 2 here! */
  4317.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4318.                   insn_info[iip].dp->dreg,
  4319.                   insn_info[iip].dp->size, &realpc, current_addr + 2,
  4320.                   eainfo, 1, EA_LOAD, bits);
  4321.  
  4322.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  4323.  
  4324.         scratch0 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4325.         lock_reg(&map, scratch0, 2);
  4326.         scratch1 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4327.         lock_reg(&map, scratch1, 2);
  4328.         scratch2 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4329.         lock_reg(&map, scratch2, 2);
  4330.         compile_force_byteorder(&map, eainfo[1].address_reg, BO_NORMAL, 0);
  4331.  
  4332.         compile_lea_reg_with_offset(scratch1, -2, (uae_u32)regs.regs);
  4333.         compile_lea_reg_with_offset(scratch2, eainfo[1].address_reg,
  4334.                         (uae_u32)(address_space + eainfo[1].addr_const_off));
  4335.  
  4336.         for (i = 0; i < 16; i++) {
  4337.             int r68k = i;
  4338.             int *cache68k = i < 8 ? map.dreg_map : map.areg_map;
  4339.             if (mask & 1
  4340.             && (i < 8
  4341.                 || insn_info[iip].dp->dmode != Aipi
  4342.                 || (r68k & 7) != insn_info[iip].dp->dreg)) {
  4343.             int tmpr = cache68k[r68k & 7];
  4344.  
  4345.             if (tmpr != -1) {
  4346.                 cache68k[r68k & 7] = -1;
  4347.                 map.x86_cache_reg[tmpr] = -1;
  4348.             }
  4349.             compile_move_reg_from_mem_regoffs(scratch0, scratch2,
  4350.                               current_offs, insn_info[iip].dp->size);
  4351.             if (size == 2) {
  4352.                 assemble(0x66); /* rolw $8,scratch0 */
  4353.                 assemble(0xC1);
  4354.                 assemble(0xC0 + scratch0);
  4355.                 assemble(8);
  4356.                 assemble(0x0F); assemble(0xBF); /* extend */
  4357.                 assemble(0xC0 + 9*scratch0);
  4358.             } else {
  4359.                 assemble(0x0F); /* bswapl scratch0 */
  4360.                 assemble(0xC8 + scratch0);
  4361.             }
  4362.             compile_move_reg_to_mem_regoffs(scratch1, (char *)(regs.regs + r68k) - (char *)regs.regs,
  4363.                             scratch0, sz_long);
  4364.             }
  4365.             if (mask & 1)
  4366.             current_offs += size;
  4367.             mask >>= 1;
  4368.         }
  4369.         }
  4370.         cc_status = 0;
  4371.         break;
  4372.  
  4373.      case i_MVMLE:
  4374.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4375.                   insn_info[iip].dp->sreg,
  4376.                   sz_word, &realpc, current_addr,
  4377.                   eainfo, 0, EA_LOAD, 1);
  4378.         sync_reg_cache(&map, 0);
  4379.         {
  4380.         int scratch0,scratch1,scratch2;
  4381.         uae_u16 mask = eainfo[0].data_const_off;
  4382.         int bits = count_bits(mask);
  4383.         int size = insn_info[iip].dp->size == sz_long ? 4 : 2;
  4384.         int i;
  4385.         uae_u8 x86amode;
  4386.         uae_u32 current_offs = 0;
  4387.         int addrareg = -1;
  4388.         if (insn_info[iip].dp->dmode == Aind
  4389.             || insn_info[iip].dp->dmode == Apdi
  4390.             || insn_info[iip].dp->dmode == Aipi
  4391.             || insn_info[iip].dp->dmode == Ad16
  4392.             || insn_info[iip].dp->dmode == Ad8r)
  4393.         {
  4394.             addrareg = get_and_lock_68k_reg(&map, insn_info[iip].dp->dreg, 0, ADDRESS_X86_REGS, 1, 2);
  4395.             compile_force_byteorder(&map, addrareg, BO_NORMAL, 0);
  4396.         }
  4397.         if (insn_info[iip].dp->dmode == Apdi)
  4398.             mask = bitswap(mask);
  4399.         /* !!! Note current_addr + 2 here! */
  4400.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4401.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4402.                   insn_info[iip].dp->dreg,
  4403.                   insn_info[iip].dp->size, &realpc, current_addr + 2,
  4404.                   eainfo, 1, EA_STORE, bits);
  4405.  
  4406.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  4407.  
  4408.         scratch0 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4409.         lock_reg(&map, scratch0, 2);
  4410.         scratch1 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4411.         lock_reg(&map, scratch1, 2);
  4412.         scratch2 = get_free_x86_register(&map, ADDRESS_X86_REGS);
  4413.         lock_reg(&map, scratch2, 2);
  4414.  
  4415.         compile_force_byteorder(&map, eainfo[1].address_reg, BO_NORMAL, 0);
  4416.  
  4417.         compile_lea_reg_with_offset(scratch1, -2, (uae_u32)regs.regs);
  4418.         compile_lea_reg_with_offset(scratch2, eainfo[1].address_reg,
  4419.                         (uae_u32)(address_space + eainfo[1].addr_const_off));
  4420.  
  4421.         for (i = 0; i < 16; i++) {
  4422.             int r68k = i;
  4423.             if (mask & 1) {
  4424.             /* move from 68k reg */
  4425.             if (i < 8 || (i & 7) != insn_info[iip].dp->dreg || addrareg == -1) {
  4426.                 compile_move_reg_from_mem_regoffs(scratch0, scratch1, (char *)(regs.regs + r68k) - (char *)regs.regs,
  4427.                                   sz_long);
  4428.             } else {
  4429.                 assemble(0x8B); assemble(0xC0 + 8*scratch0 + addrareg);
  4430.             }
  4431.  
  4432.             if (size == 2) {
  4433.                 assemble(0x66); /* rolw $8,scratch0 */
  4434.                 assemble(0xC1);
  4435.                 assemble(0xC0 + scratch0); assemble(8);
  4436.             } else {
  4437.                 assemble(0x0F); /* bswapl scratch0 */
  4438.                 assemble(0xC8 + scratch0);
  4439.             }
  4440.             compile_move_reg_to_mem_regoffs(scratch2, current_offs,
  4441.                             scratch0, insn_info[iip].dp->size);
  4442.             }
  4443.             if (mask & 1)
  4444.             current_offs += size;
  4445.             mask >>= 1;
  4446.         }
  4447.         }
  4448.         cc_status = 0;
  4449.         break;
  4450. #if 1
  4451.      case i_BTST:
  4452.      case i_BSET:
  4453.      case i_BCLR:
  4454.      case i_BCHG:
  4455.         compile_prepare_undo(&map, insn_info[iip].dp->smode, insn_info[iip].dp->sreg, &pub);
  4456.         compile_prepare_undo(&map, insn_info[iip].dp->dmode, insn_info[iip].dp->dreg, &pub);
  4457.         compile_prepareea(&map, insn_info[iip].dp->smode,
  4458.                   insn_info[iip].dp->sreg,
  4459.                   insn_info[iip].dp->size, &realpc, current_addr,
  4460.                   eainfo, 0, EA_LOAD, 1);
  4461.         compile_prepareea(&map, insn_info[iip].dp->dmode,
  4462.                   insn_info[iip].dp->dreg,
  4463.                   insn_info[iip].dp->size, &realpc, current_addr,
  4464.                   eainfo, 1, 0, 1);
  4465.  
  4466.         generate_possible_exit(&map, eainfo, iip, &pub);
  4467.         generate_possible_exit(&map, eainfo + 1, iip, &pub);
  4468.  
  4469.         handle_bit_insns(&map, eainfo, 0, 1, insn_info[iip].dp->mnemo);
  4470.         break;
  4471.  
  4472.      case i_ASL: case i_ASR: case i_LSL: case i_LSR:
  4473.      case i_ROL: case i_ROR: case i_ROXL:case i_ROXR:
  4474.         if (insn_info[iip].dp->smode == Dreg && do_rotshi) {
  4475.         handle_rotshi_variable(&map, iip, realpc, current_addr, &pub);
  4476.         break;
  4477.         }
  4478.         /* fall through */
  4479.      case i_ASLW: case i_ASRW: case i_LSLW: case i_LSRW:
  4480.      case i_ROLW: case i_RORW: case i_ROXLW:case i_ROXRW:
  4481.         if (do_rotshi) {
  4482.         handle_rotshi(&map, iip, realpc, current_addr, &pub);
  4483.         break;
  4484.         }
  4485. #endif
  4486.      default:
  4487.         generate_exit(&map, insn_info[iip].address); cc_status = 0;
  4488.         break;
  4489.     }
  4490.     if (insn_info[iip].ccuser_follows)
  4491.         cc_status_for_bcc = compile_flush_cc_cache(&map, cc_status,
  4492.                    insn_info[iip].flags_live_at_end,
  4493.                    1, insn_info[iip+1].flags_live_at_end,
  4494.                    insn_info[iip+1].dp->cc);
  4495.     else
  4496.         cc_status_for_bcc = compile_flush_cc_cache(&map, cc_status,
  4497.                    insn_info[iip].flags_live_at_end,
  4498.                    0, 0, 0);
  4499.  
  4500.     if (iip == current_bb->last_iip) {
  4501.         current_bb++;
  4502.     }
  4503.     }
  4504.     if (compile_failure)
  4505.     goto oops;
  4506.  
  4507.     /* Compile all exits that we prepared earlier */
  4508.     finish_exits();
  4509.     if (compile_failure)
  4510.     goto oops;
  4511.     finish_condjumps(last_iip);
  4512.     {
  4513.     int needed_len = compile_here() - hb->compile_start;
  4514.     int allocsize = (needed_len + PAGE_SUBUNIT - 1) & ~(PAGE_SUBUNIT-1);
  4515.     uae_u32 allocmask;
  4516.     int allocbits;
  4517.  
  4518.     allocbits = (allocsize >> SUBUNIT_ORDER);
  4519.     allocmask = (1 << allocbits) - 1;
  4520.     while ((allocmask & hb->page_allocmask) != allocmask)
  4521.         allocmask <<= 1;
  4522.     if ((hb->page_allocmask & ~allocmask) != 0 && !quiet_compile)
  4523.         fprintf(stderr, "Gaining some bits: %08lx\n", hb->page_allocmask & ~allocmask);
  4524.     hb->cpage->allocmask &= ~hb->page_allocmask;
  4525.     hb->page_allocmask = allocmask;
  4526.     hb->cpage->allocmask |= allocmask;
  4527.     }
  4528.     return 0;
  4529.  
  4530.     oops:
  4531.     if (1 || !quiet_compile)
  4532.     fprintf(stderr, "Compile failed!\n");
  4533.     hb->cpage->allocmask &= ~hb->page_allocmask;
  4534.     hb->cpage = NULL;
  4535.     hb->untranslatable = 1;
  4536.     {
  4537.     struct hash_entry *h = hb->he_first;
  4538.  
  4539.     do {
  4540.         h->execute = NULL;
  4541.         h = h->next_same_block;
  4542.     } while (h != hb->he_first);
  4543.     }
  4544.     return 1;
  4545. }
  4546.  
  4547. void compiler_init(void)
  4548. {
  4549.     code_init();
  4550.     hash_init();
  4551.     jsr_stack_init();
  4552. }
  4553.  
  4554. /*
  4555.  * Why do compilers always have to be so complicated? And I thought GCC was
  4556.  * a mess...
  4557.  */
  4558.  
  4559. #endif /* USE_COMPILER */
  4560.